Android切换主线程更新UI方法总结

一、归纳总结

1. view.post(Runnable action)

2. activity.runOnUiThread(Runnable action)

3. Handler机制

4. 使用AsyncTask

 

二、详细介绍及示例

方法一: 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 依附的消息队列中(也就是主线程消息队列)。

如下假如该方法是在子线程中

    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毫秒再发送消息

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

方法四: 使用AsyncTask

/**

  * 该类中方法的执行顺序依次为:onPreExecute, doInBackground, onPostExecute

  */

    private class MyAsyncTask extends AsyncTask {

  /**

         * 主线程中执行

         * 在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这只是他们的冰山一角!

 

更多相关文章

  1. android Log.isLoggable方法的使用
  2. Android 软件盘弹出时把顶部局顶上去的解决方法
  3. android的singleInstance启动模式及方法调用
  4. Android 中数据库查询方法 query() 中的 selectionArgs 的用法
  5. Android中设置中文粗体的方法
  6. RelativeLayout相对布局方法总结
  7. Android 多线程编程 一个游戏程序员的学习资料
  8. 两种button点击后改变颜色的方法selectot和重写

随机推荐

  1. 如何在 Android(安卓)手机上运行 Node.js
  2. Android(安卓)adb shell 命令
  3. (Android小应用)电话监听器
  4. android log丢失(三)动态切换logd机制和ker
  5. android 优化Lint清除无效资源文件的用法
  6. 利用9-Patch PNG来实现ListView的圆角显
  7. Android(安卓)Studio中调用高于minSdkVer
  8. Android(安卓)Fragment生命周期——多屏
  9. [视频]Firefox for Android(安卓)预览版
  10. Android网络基础1——网络分层