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)来切换到主线程。

  1. Fragment中获取上下文,刷新页面
 @Override
    public void ResultFollowSuccess(String value, int position) {
        Activity context = getActivity();

        context.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                FollowBean.CardBean cardBean = cardList.get(position);
                ////当前用户是否关注了该帖子的发帖人    0:未关注 1:已关注
                cardBean.setIs_attention(1);
                followAdapter.notifyItemChanged(position);
                ToastUtils.showShort("关注成功");
            }
        });

    }

方法三: 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的目的。

————————————————
参考链接:https://blog.csdn.net/paladinzh/article/details/87254232

你可能感兴趣的:(Android切换主线程更新UI方法总结)