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

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

 

你可能感兴趣的:([Mobile]Android)