美文网首页
2019-04-23android进行异步更新控件的四种方式

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

作者: 奥雷里亚诺下划线_上校 | 来源:发表于2019-04-23 15:02 被阅读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
    可以省下大量的代码量。

    相关文章

      网友评论

          本文标题:2019-04-23android进行异步更新控件的四种方式

          本文链接:https://www.haomeiwen.com/subject/dpamgqtx.html