Android基础——实现子线程更新UI

Android中线程按功能分的话,可以分为两个,一个是主线程(UI线程),其他的都是子线程。

主线程不能执行那些耗时过长的代码或任务(执行耗时过长的代码会出现应用未响应的提示),所以都是使用子线程来执行耗时过长的代码,比如说下载文件等任务。

一般情况,子线程中执行过长的代码,都是需要进行更新UI操作。

但是Android中,为了防止安全,是不允许在子线程更新UI的,但是我们可以使用到Android官方给予的API来实现子线程更新UI的操作(本质上,这些API也是切换回了主线程来进行更新UI)

1、runOnUiThread

    private  void makeToastByRunOnUiThread(final String msg)
    {
        LoginActivity.this.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(LoginActivity.this, msg, Toast.LENGTH_SHORT).show();
            }
        });
    }

2、view.post

   //方法五:通过view.post,更新UI主线程
    private void makeToatByViewPost(View view,final String msg)
    {
        view.post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(LoginActivity.this, msg, Toast.LENGTH_SHORT).show();
            }
        });
    }
 

3、handler.post

    private Handler handler = new Handler()
    private void makeToastByHandlerPost(final String msg)
    {
        handler.post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(LoginActivity.this, msg, Toast.LENGTH_SHORT).show();
            }
        });
    }

4、handler.postDelayed

    private Handler handler = new Handler()
    private void makeToastByHandlerPostDelay(final String msg,int seconds)
    {
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(LoginActivity.this, msg, Toast.LENGTH_SHORT).show();
            }
        },seconds*1000);
    }

5、AsyncTask

public abstract class AsyncTask<Params, Progress, Result> { 
 ... 
 }
参数 说明
params 参数泛型,doInBackground方法的参数
progress 进度泛型,onProgressUpdate方法的参数
result 结果泛型,onPostExecute方法的参数
/**
  * 步骤1:创建AsyncTask子类
  * 注: 
  *   a. 继承AsyncTask类
  *   b. 为3个泛型参数指定类型;若不使用,可用java.lang.Void类型代替
  *   c. 根据需求,在AsyncTask子类内实现核心方法
  */

  private class MyTask extends AsyncTask<Params, Progress, Result> {

        ....

      // 方法1:onPreExecute()
      // 作用:执行 线程任务前的操作
      // 注:根据需求复写
      @Override
      protected void onPreExecute() {
           ...
        }

      // 方法2:doInBackground()
      // 作用:接收输入参数、执行任务中的耗时操作、返回 线程任务执行的结果
      // 注:必须复写,从而自定义线程任务
      @Override
      protected String doInBackground(String... params) {

            ...// 自定义的线程任务

            // 可调用publishProgress()显示进度, 之后将执行onProgressUpdate()
             publishProgress(count);
              
         }

      // 方法3:onProgressUpdate()
      // 作用:在主线程 显示线程任务执行的进度
      // 注:根据需求复写
      @Override
      protected void onProgressUpdate(Integer... progresses) {
            ...

        }

      // 方法4:onPostExecute()
      // 作用:接收线程任务执行结果、将执行结果显示到UI组件
      // 注:必须复写,从而自定义UI操作
      @Override
      protected void onPostExecute(String result) {

         ...// UI操作

        }

      // 方法5:onCancelled()
      // 作用:将异步任务设置为:取消状态
      @Override
        protected void onCancelled() {
        ...
        }
  }

/**
  * 步骤2:创建AsyncTask子类的实例对象(即 任务实例)
  * 注:AsyncTask子类的实例必须在UI线程中创建
  */
  MyTask mTask = new MyTask();

/**
  * 步骤3:手动调用execute(Params... params) 从而执行异步线程任务
  * 注:
  *    a. 必须在UI线程中调用
  *    b. 同一个AsyncTask实例对象只能执行1次,若执行第2次将会抛出异常
  *    c. 执行任务中,系统会自动调用AsyncTask的一系列方法:onPreExecute() 、doInBackground()、onProgressUpdate() 、onPostExecute() 
  *    d. 不能手动调用上述方法
  */
  mTask.execute()

抽象方法说明:

方法名 说明
onPreExectute() 此方法中,常常进行初始化操作,如进度条显示
doInBackground(Params…) 此方法必须实现,
onProgressUpdate(Progress…) 进行更新UI的操作
publishProgress(Progress…) 在doInBackground方法中调用,调用此方法后会回调执行onProgressUpdate方法进行更新UI
onPostExcute(Result) 任务结束之后进行更新UI

6、Handler机制

其实,Handler机制是子进程更新UI的核心
我们上面的五种实现子进程更新UI的方式,都是基于Handler机制实现
在这里插入图片描述

  //定义handler
    static  final int SUCCESS=1;
    static  final int FAIL=0;
    Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case SUCCESS:
                    Toast.makeText(LoginActivity.this, msg.getData().get("msg").toString(), Toast.LENGTH_SHORT).show();
                    break;
                case FAIL:
                    Toast.makeText(LoginActivity.this, msg.getData().get("msg").toString(), Toast.LENGTH_SHORT).show();
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    };

    private void makeToastByHandlerSendMessage(String msgStr)
    {
        Message msg=new Message();
        msg.what=0;
        Bundle bundle=new Bundle();
        bundle.putString("msg",msgStr);
        msg.setData(bundle);
        handler.sendMessage(msg);
    }

7、注解框架

导包

implementation 'androidx.appcompat:appcompat:1.1.0'

@UiThread: UI线程
@MainThread :主线程
@WorkerThread: 子线程
@BinderThread : 绑定线程

在对应得方法前使用注解就可以了。


	@UiThread
	void runInUiThread(int result) {
		Toast.makeText(context, result + ", just a test",Toast.LENGTH_SHORT).show();
	}
	
 	@WorkerThread
    private void testDo(@StringRes int str){
        Log.e("tag","-------->"+getString(str));
    }
发布了63 篇原创文章 · 获赞 1 · 访问量 2101

猜你喜欢

转载自blog.csdn.net/weixin_42046829/article/details/105413195
今日推荐