最近看了网上,在子线程更新UI的方法,说法很多,但都不是很全面。在此我争取做到总结的全面一些,希望以后对自己,对大家都有一些帮助。

方法一: view.post(Runnable action)

假如该方法是在子线程中

textView.post(new Runnable() {        @Override        public void run() {            textView.setText("更新textView");            //还可以更新其他的控件            imageView.setBackgroundResource(R.drawable.update);        }    });

这是view自带的方法,比较简单,如果你的子线程里可以得到要更新的view的话,可以用此方法进行更新。

view还有一个方法view.postDelayed(Runnable action, long delayMillis)用来延迟发送。


方法二: activity.runOnUiThread(Runnable action)

假如该方法是在子线程中

注意:context 对象要是 主线程中的MainActivity,这样强转才可以。

public void updateUI(final Context context) {        ((MainActivity) context).runOnUiThread(new Runnable() {            @Override            public void run() {                //此时已在主线程中,可以更新UI了            }        });    }

如果没有上下文(context),试试下面的方法:
1.用view.getContext()可以得到上下文。
2.跳过context直接用new Activity().runOnUiThread(Runnable action)来切换到主线程。


方法三: Handler机制

首先在主线程中定义Handler,Handler mainHandler = new Handler();(必须要在主线程中定义才能操作主线程,如果想在其他地方定义声明时要这样写Handler mainHandler = new Handler(Looper.getMainLooper()),来获取主线程的 Looper 和 Queue )

获取到 Handler 后就很简单了,用handler.post(Runnable r)方法把消息处理放在该 handler 依附的消息队列中(也就是主线程消息队列)。

(1):假如该方法是在子线程中

    Handler mainHandler = new Handler(Looper.getMainLooper());    mainHandler.post(new Runnable() {        @Override        public void run() {            //已在主线程中,可以更新UI        }    });

Handler还有下面的方法:
1.postAtTime(Runnable r, long uptimeMillis); //在某一时刻发送消息
2.postAtDelayed(Runnable r, long delayMillis); //延迟delayMillis毫秒再发送消息

(2): 假设在主线程中

    Handler myHandler = new Handler() {        @Override        public void handleMessage(Message msg) {            switch(msg.what) {                case 0:                    //更新UI等                    break;                case 1:                     //更新UI等                    break;                default:                    break;            }        }    }

之后可以把 mainHandler 当做参数传递在各个类之间,当需要更新UI时,可以调用sendMessage一系列方法来执行handleMessage里的操作。

假设现在在子线程了

    /**      *获取消息,尽量用obtainMessage()方法,查看源码发现,该方法节省内存。      *不提倡用Messenger msg=new Messenger()这种方法,每次都去创建一个对象,肯定不节省内存啦!      *至于为什么该方法还存在,估计还是有存在的必要吧。(留作以后深入研究)      */    Message msg = myHandler.obtainMessage();    msg.what = 0; //消息标识    myHandler.sendMessage(msg); //发送消息

如上代码,只是发送了个消息标识,并没有传其他参数。
如果想传递参数,可以这样:

      msg.what = 1;  //消息标识      msg.arg1=2;   //存放整形数据,如果携带数据简单,优先使用arg1和arg2,比Bundle更节省内存。      msg.arg2=3;   //存放整形数据      Bundle bundle=new Bundle();      bundle.putString("dd","adfasd");      bundle.putInt("love",5);      msg.setData(bundle);      msg.obj=bundle;   //用来存放Object类型的任意对象      myHandler.sendMessage(msg); //发送消息            

总结: msg.obj它的功能比较强大一下,至于它和利用Bundle传递数据,那个会效率高一些,更节省内存一些。个人认为:从传递数据的复杂程度看,由简单到复杂依次使用,arg1, setData(), obj。会比较好一些。

当然可以用简化方法sendEmptyMessage(int what)来减少不必要的代码,这样写:

 myHandler.sendEmptyMessage(0); //其实内部实现还是和上面一样

发送消息的其他方法有:

endEmptyMessageAtTime(int what, long uptimeMillis); //定时发送空消息sendEmptyMessageDelayed(int what, long delayMillis); //延时发送空消息sendMessageAtTime(Message msg, long uptimeMillis); //定时发送消息sendMessageDelayed(Message msg, long delayMillis); //延时发送消息sendMessageAtFrontOfQueue(Message msg); //最先处理消息(慎用)

方法四: 使用AsyncTask

/**  * 该类中方法的执行顺序依次为:onPreExecute, doInBackground, onPostExecute  */    private class MyAsyncTask extends AsyncTask<String, Integer, String> {        /**         * 主线程中执行         * 在execute()被调用后首先执行         * 一般用来在执行后台任务前对UI做一些标记         */        @Override        protected void onPreExecute() {            super.onPreExecute();            System.out.println("MyAsyncTask.onPreExecute");        }        /**         * 子线程中执行,执行一些耗时操作,关键方法         * 在执行过程中可以调用publishProgress(Progress... values)来更新进度信息。         */        @Override        protected String doInBackground(String... params) {            System.out.println("MyAsyncTask.doInBackground");            //只是模拟了耗时操作            int count = 0;            for (int i = 0; i < 10; i++) {                try {                    count++;                    publishProgress((count % 100) * 10);                    Thread.sleep(3000);                } catch (InterruptedException e) {                    e.printStackTrace();                }            }            // publishProgress((int) ((count / (float) total) * 100));            return "耗时操作执行完毕";        }        /**         * 主线程中执行         * 在调用publishProgress(Progress... values)时,此方法被执行,直接将进度信息更新到UI组件中         */        @Override        protected void onProgressUpdate(Integer... values) {            super.onProgressUpdate(values);            progressBar.setProgress(values[0]);            textView.setText("loading..." + values[0] + "%");            System.out.println("MyAsyncTask.onProgressUpdate");        }        /**         * 在主线程中,当后台操作结束时,此方法将会被调用         * 计算结果将做为参数传递到此方法中,直接将结果显示到UI组件上。         */        @Override        protected void onPostExecute(String aVoid) {            super.onPostExecute(aVoid);            System.out.println("MyAsyncTask.onPostExecute aVoid=" + aVoid);            textView.setText(aVoid);        }        /**         * 主线程中执行         * 当异步任务取消后的,会回调该函数。在该方法内可以更新UI         */        @Override        protected void onCancelled() {            super.onCancelled();            System.out.println("MyAsyncTask.onCancelled");            progressBar.setProgress(0);            textView.setText("0");        }        @Override        protected void onCancelled(String s) {            super.onCancelled(s);        }    }

注意:doInBackground方法是在子线程中,所以,我们在这个方法里面执行耗时操作。同时,由于其返回结果会传递到onPostExecute方法中,而onPostExecute方法工作在UI线程,这样我们就在这个方法里面更新ui,达到了异步更新ui的目的。


对于android的异步加载数据及更新ui,我们不仅可以选择AsyncTask异步任务,还可以选择许多开源的网络框架,如: 点击进入了解更多 xUtils3,AsyncHttpClient,Okhttp,Volley,…,
这些优秀的网络框架让我们异步更新ui变得非常简单,而且,效率和性能也非常高。当然这些网络框架绝不仅仅就这么个功能,异步更新UI这只是他们的冰山一角!

更多关于android网络框架详细内容请点击此处


更多相关文章

  1. Android(安卓)N Settings 架构剖析
  2. Android(安卓)四大组件流程、Handler、AsyncTask、IntentService
  3. Android(安卓)插件化分析(3)- Activity启动流程
  4. Android理解:IntentService
  5. 使用 Eclipse 调试 android 程序(debug 方法)
  6. 个人android工具包——androidkit更新
  7. Android中AppWidget加载流程(二)
  8. Android(安卓)x86模拟器Intel Atom x86 System Image配置与使用
  9. Android(安卓)Intent传递对象的两种方法(Serializable,Parcelabl

随机推荐

  1. android四种不同的事件实现
  2. Utilize Avahi Libraries in Android(安
  3. Android:入门级Android开发者应该知道的
  4. Unity3d - Android(安卓)Build : Android
  5. Android2.2 官方下载地址
  6. android日历实现__GO桌面版&&开源收藏版
  7. Android--Alarm,定时闹钟
  8. android 加密字符串
  9. Android™ 1.5 android.R.drawable Icon
  10. Android(安卓)luancher消息提醒-Shortcut