2019-04-23android进行异步更新控件的四种方式

2019-04-23  本文已影响0人  奥雷里亚诺下划线_上校

最近在尝试在app里对接百度ai的相关图片试别的api,发现网络请求是无法写在主线程中的(网路请求还需要申请权限),主要原因大致和主线程为了保护ui控件的正常使用而生成的一种保护机制。

1.Handler消息传递机制

public class MainActivity4Handler extends AppCompatActivity {
    private TextView tv;

    //事件更新器
    Handler handler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            if (msg.what == 0x123) {
                //符合条件,更新控件
                tv.setText("更新后的TextView:" + (String) msg.obj);
            }
        }     
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = (TextView) findViewById(R.id.tv);
        new MyThread().start();//   启动一个新线程
    }

    class MyThread extends Thread {
        @Override
        public void run() {
            //异步处理事件
            //延迟两秒更新
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            //传递消息(只传递一个数字)
            //handler.sendEmptyMessage(0x123);
            //传递一个message对象
            Message message = new Message();
            String x = "ssss";
            message.what = 0x123;
            message.obj = x;//这里可以传json字符串
            handler.sendMessage(message);
        }
    }
}

2. 使用AsyncTask异步任务

public class MainActivity4Async extends AppCompatActivity {
    private TextView tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = (TextView) findViewById(R.id.tv);
        new Yibu().execute(tv);//执行异步
    }

    //泛型参数分别代表,传入,中间,返回值
    class Yibu extends AsyncTask<TextView, String, String>{

        //预处理,可以随意提示一些信息
        @Override
        protected void onPreExecute() {
            Toast.makeText(MainActivity4Async.this, "这里是预处理", Toast.LENGTH_SHORT).show();
        }

        //调用publishProgress()方法后,该方法会很快执行,利用方法中携带的参数进行对界面进行刷新
        @Override
        protected void onProgressUpdate(String... values) {
            for (int i = 0; i < values.length; i++) {
                tv.setText(values[i]);
            }
        }

        //执行后台程序
        @Override
        protected String doInBackground(TextView... views) {
            //比如耗时多的联网操作等
            TextView tv = views[0];
            tv.setText("中途更新");

            publishProgress("string 字符串,可以是json格式,用来传递执行完成后的结果");
            return null;
        }

        //后台任务执行完毕后,可以通过此方法进行提示
        @Override
        protected void onPostExecute(String s) {
            Toast.makeText(MainActivity4Async.this, "处理完成", Toast.LENGTH_SHORT).show();

        }
    }
}

3. 使用runOnUiThread(action)方法

public class MainAc4UiThread extends AppCompatActivity {
    private TextView tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = (TextView) findViewById(R.id.tv);
        new MyThread().start();//必须在Activity中实现
    }

    class MyThread extends Thread {
        @Override
        public void run() {
            //写这个方法,表示新开的ui更新线程
            runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    try {
                        //延迟两秒更新
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    tv.setText("更新后的TextView");
                }
            });
        }
    }
}

4. 使用Handler的post(Runnabel r)方法

这个没什么特别的,核心代码块。

 Handler handler = new Handler();
        handler.post(new Runnable(){
            @Override
            public void run() {
                try {
                    //延迟两秒更新
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                tv.setText("更新后的TextView");
            }

综合四种用法,个人还是喜欢使用使用第二种,生命周期很清楚,同时也是官方提供的一种方法,也便于实现代码的分离,在异步使用不多的情况下推荐使用。


最后更新一下,理解了以上四种原理后推荐使用RxAndroid框架,具体的文章可以参阅https://www.jianshu.com/p/1cad42c4bc04
可以省下大量的代码量。

上一篇下一篇

猜你喜欢

热点阅读