Android线程


Android线程

最近学习了Android多线程和异步任务,因此整理出以下笔记

子线程中进行UI操作

在Android中子线程是不能直接对UI控件直接操作的,否则会报android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views的错误

因此我们需要先把子线程切换到主线程后再对其进行操作

使用Handler

在Android中要进行多个线程的通讯Handler是用的比较频繁的,它负责发送和处理消息,可以通过它来实现其他线程和主线程之间通信。

以下案例实现点击Button后改变Button的文字

//监听Button
public void btnOnClick(View view) {
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            handler.sendEmptyMessage(1);
        }
    }).start();
}

private Handler handler = new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            if (msg.what == 1){
                btn_1.setText("123");
            }
        }
    };

使用Post

我们还可以使用View的post()方法

private void thread() {
    new Thread(new Runnable() {
        @Override
        public void run() {
           btn_1.post(new Runnable() {
               @Override
               public void run() {
                   btn_1.setText("123");
               }
           });
        }
    }).start();
}

使用runOnUiThread

也可以使用Activity的runOnUiThread()方法

private void thread() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    btn_1.setText("123");
                }
            });
        }
    }).start();
}

AsynTask异步任务

AsynTask是多线程编程的一个框架,它介于Thread和handler之间,可以更加高效的在主线程和子线程之间进行切换。

AsynTask的基本使用

AsynTask是一个抽象类,我们需要自定义一个类来实现它的doInBackground方法然后调用TestTask().execute()方法即可。

class TestTask extends AsyncTask<Void,Void,String>{

    @Override
    protected String doInBackground(Void... voids) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String str = "ABC";

        return str;
    }

}

AsynTask的四大方法

onPreExecute()

此方法在后台任务开始前调用,用于初始化界面上的一些操作

@Override
protected void onPreExecute() {
    super.onPreExecute();
    Log.d("TAG","onPreExecute");

}

doInBackground()

这个方法是子线程,用作处理耗时任务,也是我们代码主要书写的地方,如果中途需要更新UI则调用publishProgress()后重写onProgressUpdate()方法。

最后的return返回的结果会传递给onPostExecute(),用作更新UI操作

@Override
protected String doInBackground(Void... voids) {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    String str = "ABC";

    return str;
}

onProgressUpdate()

这个方法用于接收publishProgress()传入的参数,从而更新控件。

@Override
protected void onProgressUpdate(Void... values) {
    super.onProgressUpdate(values);
    Log.d("TAG","onProgressUpdate");
}

onPostExecute()

这个方法可以接收doInBackground()所返回的内容,进行UI控件的操作

@Override
protected void onPostExecute(String s) {
    super.onPostExecute(s);
    btn_1.setText(s);
}

案例模拟进度条

@Override
protected void onPreExecute() {
    super.onPreExecute();
    Toast.makeText(ExecutorServiceTest.this, "开始下载", Toast.LENGTH_SHORT).show();
}

@Override
protected Boolean doInBackground(Void... voids) {
    try {
        while (true){
            Thread.sleep(500);
            pb += 10;
            publishProgress(pb);
            if (pb >= 100){
                break;
            }
        }
    } catch (InterruptedException e) {
       return false;
    }
    return true;
}

@Override
protected void onProgressUpdate(Integer... values) {
    super.onProgressUpdate(values);
    pb_1.setProgress(values[0]);
}

@Override
protected void onPostExecute(Boolean aBoolean) {
    super.onPostExecute(aBoolean);
    if (aBoolean){
        Toast.makeText(ExecutorServiceTest.this, "下载成功", Toast.LENGTH_SHORT).show();
        pb_1.setVisibility(View.GONE);
    }else {
        Toast.makeText(ExecutorServiceTest.this, "下载失败", Toast.LENGTH_SHORT).show();
        pb_1.setVisibility(View.GONE);
    }
}

文章作者: 落樱
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 落樱 !
评论
  目录