当前位置:  编程技术>移动开发
本页文章导读:
    ▪关于在非UI线程中更新UI控件不会crash的有关问题        关于在非UI线程中更新UI控件不会crash的问题 昨天同事问我一个问题,在Thread中去更新一个Button的状态可行吗?我说当然不行。他告诉我说,那为什么他的程序不会奔溃,我过去一看果然没有.........
    ▪ NSString中 initwithformat与stringwithformat差异        NSString中 initwithformat与stringwithformat区别 差别:1、initWithFormat是实例办法只能经由过程 NSString* str = [[NSString alloc] initWithFormat:@"%@",@"Hello World"] 调用,然则必须手动release来开释内存资.........
    ▪ git merger 其后add 将状态改为resolve       git merger 然后add 将状态改为resolve 。有冲突的话,git会提示那个文件中有冲突,比如有如下冲突:<<<<<<< HEAD:test.cprintf (“test1″);=======printf (“test2″);>>>>>>> i.........

[1]关于在非UI线程中更新UI控件不会crash的有关问题
    来源: 互联网  发布时间: 2014-02-18
关于在非UI线程中更新UI控件不会crash的问题

昨天同事问我一个问题,在Thread中去更新一个Button的状态可行吗?我说当然不行。他告诉我说,那为什么他的程序不会奔溃,我过去一看果然没有奔溃,甚是奇怪。难道是我记错了?于是我Google了一下。发现Android的开发文档中确实说这样是不行的啊。

http://developer.android.com/guide/components/processes-and-threads.html

 

  • Do not access the Android UI toolkit from outside the UI thread
  •  

    public void onClick(View v) {
        new Thread(new Runnable() {
            public void run() {
                Bitmap b = loadImageFromNetwork("http://example.com/image.png");
                mImageView.setImageBitmap(b);
            }
        }).start();
    }

     it violates the second rule of the single-threaded model: do not access the Android UI toolkit from outside the UI thread—this sample modifies the ImageView from the worker thread instead of the UI thread. This can result in undefined and unexpected behavior, which can be difficult and time-consuming to track down.

     

     

    再看看我同事的代码:

     

    public class MainActivity extends Activity
    {
    
    	private Button btn;
    	@Override
    	protected void onCreate(Bundle savedInstanceState)
    	{
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		btn = (Button)findViewById(R.id.btn);
    		startAThread();
    	}
    	
    	private void startAThread()
    	{
    		new Thread(new Runnable() {
    			
    			@Override
    			public void run()
    			{
    				btn.setText("Hello Michael!");
    			}
    		}).start();
    	}
    }

     

     

    没有发现什么大的区别,唯一的区别就在于执行的地方不太一样,Google官方文档是在onClick的时候去执行,而同事的代码是在onCreate的时候执行。于是我做了一些修改,增加一个onClick事件:

     

     

    public class MainActivity extends Activity
    {
    
    	private Button btn;
    	@Override
    	protected void onCreate(Bundle savedInstanceState)
    	{
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		btn = (Button)findViewById(R.id.btn);
    		
    		btn.setOnClickListener(new OnClickListener() {
    			
    			@Override
    			public void onClick(View v)
    			{
    				startAThread();
    			}
    		});
    		startAThread();
    	}
    
    	private void startAThread()
    	{
    		new Thread(new Runnable() {
    			
    			@Override
    			public void run()
    			{
    				btn.setText("Hello Michael!");
    			}
    		}).start();
    	}
    
    }
    

     

     

    果然,程序在onClick的时候crash了。

    但是为什么呢?在onCreate的时候去不会crash呢?

     

    我们看一下错误:

     

    这个错误相信大家都有遇到过,意思就是说不能在非UI线程中去更新UI控件。顺着这个错误,

    到源码中去查找一下ViewRootImpl.java这个文件。你可以看到这个异常:

     

    void checkThread() {
            if (mThread != Thread.currentThread()) {
                throw new CalledFromWrongThreadException(
                        "Only the original thread that created a view hierarchy can touch its views.");
            }
        }

     

     

    这个方法就是用来判断更新UI控件的时候是否在UI线程中进行,如果不是的话就会报错。也就是onCreate的时候这个判断没有被执行到,因此onCreate中启动的Thread并不会导致程序的crash。

     

    不知道这算不算Google的一个bug呢,虽然这样没有什么问题,但是也不建议大家这样做。因为这样可能会卡住UI线程,而且也没有必要这样做,Activity.runOnUiThread,View.Post,或者麻烦一点用AsyncTask,Handler这样的方式来处理都是Google比较推荐的做法。

     

     

     

     


        
    [2] NSString中 initwithformat与stringwithformat差异
        来源: 互联网  发布时间: 2014-02-18
    NSString中 initwithformat与stringwithformat区别
    差别:

    1、initWithFormat是实例办法

    只能经由过程 NSString* str = [[NSString alloc] initWithFormat:@"%@",@"Hello World"] 调用,然则必须手动release来开释内存资料

    2、stringWithFormat是类办法
    自动释放内存
    可以直接用 NSString* str = [NSString stringWithFormat:@"%@",@"Hello World"] 调用,内存经管上是autorelease的,不用手动显式release


    别的国外有个贴子对此有专门评论辩论(http://www.iphonedevsdk.com/forum/iphone-sdk-development/29249-nsstring-initwithformat-vs-stringwithformat.html)

    并且提出了一个常见错误:

    label.text = [[NSString alloc] initWithFormat:@"%@",@"abc"];

    最后在dealloc中将label给release掉

    然则仍然会产生内存泄漏!

    原因在于:用label.text = ...时,实际是隐式调用的label的setText办法,这会retain label内部的字符串变量text(哪怕这个字符串的内容跟传进来的字符串内容雷同,但体系仍然当成二个不合的字符串对象),所以最后release label时,实际上只开释了label内部的text字符串,然则最初用initWithFormat生成的字符串并未开释,终极造成了泄漏。

    解决办法有二个:

    1、

    NSString * str = [[NSString alloc] initWithFormat:@"%@",@"abc"];

    label.text = str;

    [str release]

    最后在dealloc中再[label release]

    2、

    label.text = [NSString stringWithFormat:@"%@",@"abc"];

    然后剩下的工作交给NSAutoreleasePool

    最后,若是你不断定你的代码是否有内存泄漏题目,可以用Xcode中的Build-->Build And Analyze 做初步的搜检

        
    [3] git merger 其后add 将状态改为resolve
        来源: 互联网  发布时间: 2014-02-18
    git merger 然后add 将状态改为resolve
    。有冲突的话,git会提示那个文件中有冲突,比如有如下冲突:

    <<<<<<< HEAD:test.c

    printf (“test1″);

    =======

    printf (“test2″);

    >>>>>>> issueFix:test.c

    可以看到 ======= 隔开的上半部分,是 HEAD(即 master 分支,在运行 merge 命令时检出的分支)中的内容,下半部分是在 issueFix 分支中的内容。解决冲突的办法无非是二者选其一或者由你亲自整合到一起。比如你可以通过把这段内容替换为下面这样来解决:

    printf (“test2″);

    这个各采纳了两个分支中的一部分内容,而且删除了 <<<<<<<,=======,和>>>>>>> 这些行。在解决了所有文件里的所有冲突后,运行 git add 将把它们标记为已解决(resolved)。然后使用git commit命令进行提交,merge就算完成了

        
    最新技术文章:
    ▪Android开发之登录验证实例教程
    ▪Android开发之注册登录方法示例
    ▪Android获取手机SIM卡运营商信息的方法
    ▪Android实现将已发送的短信写入短信数据库的...
    ▪Android发送短信功能代码
    ▪Android根据电话号码获得联系人头像实例代码
    ▪Android中GPS定位的用法实例
    ▪Android实现退出时关闭所有Activity的方法
    ▪Android实现文件的分割和组装
    ▪Android录音应用实例教程
    ▪Android双击返回键退出程序的实现方法
    ▪Android实现侦听电池状态显示、电量及充电动...
    ▪Android获取当前已连接的wifi信号强度的方法
    ▪Android实现动态显示或隐藏密码输入框的内容
    ▪根据USER-AGENT判断手机类型并跳转到相应的app...
    ▪Android Touch事件分发过程详解
    ▪Android中实现为TextView添加多个可点击的文本
    ▪Android程序设计之AIDL实例详解
    ▪Android显式启动与隐式启动Activity的区别介绍
    ▪Android按钮单击事件的四种常用写法总结
    ▪Android消息处理机制Looper和Handler详解
    ▪Android实现Back功能代码片段总结
    ▪Android实用的代码片段 常用代码总结
    ▪Android实现弹出键盘的方法
    ▪Android中通过view方式获取当前Activity的屏幕截...
    ▪Android获取手机SIM卡运营商信息的方法 iis7站长之家
    ▪Android提高之多方向抽屉实现方法
    ▪Android提高之MediaPlayer播放网络音频的实现方法...
    ▪Android提高之MediaPlayer播放网络视频的实现方法...
    ▪Android提高之手游转电视游戏的模拟操控
     


    站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3