栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Android线程问题解决——Thread+Handler的使用和AsyncTask的使用(外加安卓进度条的代码实现)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android线程问题解决——Thread+Handler的使用和AsyncTask的使用(外加安卓进度条的代码实现)

文章目录

问题引入线程知识

  主线程(UI线程)  子线程 解决方案

  一,使用Thread+Handler处理

     1.概念     2.流程图     3.过程概述     4.代码实现   二,用AsyncTask处理

     1.概念(异步执行的四个方法)     2.流程图     3.AsyncTask异步任务使用时的注意事项     4.AsyncTask异步任务代码实现进度条 总结

问题引入

 Android用户界面是与用户交互的接口,对于用户的操作,Android迅速响应用户输入(200ms内)是一个重要目标。
若用户界面长时间对用户的操作未作出响应,那么这样的应用程序,肯定不会受到用户的广泛青睐。
此类问题案例很多:如后台下载、异步加载图片等等。
对于这类耗时比较多的工作,一般是使用多线程的方法来解决的。

线程知识   主线程(UI线程)

   Android应用刚启动时,会在当前应用所对应的进程中启动一个主线程(也叫UI线程);
该UI线程处理与UI相关的事件,如:用户的按键事件,把相关的事件分派到对应的组件进行处理等。

  子线程

  1.对于UI线程中比较耗时的工作,开启一个子线程来处理这些工作:首先创建一个Thread 对象,然后调用start( )方法 启动新的子线程。

  2.使用子线程解决异步执行:
    (1)带来的新问题:在Android中,只有 UI线程 (即主线程)才可以更新主UI界面,而 子线程不能更新UI界面。
    (2)解决方案(既要异步执行,又要解决更新UI界面的问题):
      ①使用多线程实现Thread+Handler
      ②使用AsyncTask

解决方案   一,使用Thread+Handler处理      1.概念
	      Thread:子线程,用来处理耗时的操作。
	      
	      Handler:接受子线程发送的数据,并用此数据配合主线程更新UI
	        - Handler定义在主线程中(UI线程中)
	        - Handler充当主线程和子线程中间交互的中介:
	           • Handler在新启动的子线程中发送消息
	           • Handler在主线程中获取并处理子线程所发送的消息
     2.流程图

     3.过程概述

      ①首先UI线程创建的同时,会初始化一个Looper对象以及其关联的MessageQueue。
      ②创建一个工作子线程进行耗时工作的完成。
      ③通过引用的MyHandler,来发送携带信息的Message对象到MessageQueue。
      ④MessageQueue:消息队列,先进先出管理Message,在初始化Looper对象时会创建一个与之关联的MessageQueue;
      ⑤Looper管理MessageQueue, 取出Message分发给MyHandler处理(每个主线程只有一个Looper)

     4.代码实现

      ①创建Thread对象,在Thread对象的run方法中发送消息。

Thread thread= new Thread() {
    public void run() {
        Message msg = handler.obtainMessage();
        msg.what = MSG_CURRENT;
        msg.obj=1;
        handler.sendMessage(msg);
    }
};
thread.start();

      ②创建Handler对象(自定义的匿名子类方法),并添加handleMessage方法

private Handler handler = new Handler() {
    public void handleMessage (Message msg) {
        switch (msg.what) {
            case MSG_CURRENT: // TODO
            	TextView.setText(msg.obj);
            	break;
        }
    }
};
  二,用AsyncTask处理      1.概念(异步执行的四个方法)

      ①onPreExecute():任务被执行之前调用UI线程。
       • 运行在UI线程中,任务执行前的准备,比如弹出进度条

      ②doInBackground(Params…):onPreExecute()执行完成,立刻调用后台线程。
       • 这步被用于执行较长时间的后台任务;
       • 子线程中运行,将执行结束的结果返回onPostExecute()参数中

      ③onProgressUpdate(Progress…):运行在UI线程中,更新当前进度条信息,被publishProgress回调。
       • 这个方法用于在用户界面显示进度,当后台计算还在进行时
       • 例如:这个方法可以被用于一个进度条动画或在文本域显示日志。

      ④onPostExecute(Result):当后台计算结束时,调用UI线程。
       • 运行在UI线程中,处理异步线程的任务结果。

     2.流程图

     3.AsyncTask异步任务使用时的注意事项

        ①AsyncTask必须被子类继承。
        ②子类至少重写其中的doInBackground(Params…)方法,一般还会重写onPostExecute(Result)。
        ③任务实例必须创建在UI线程。
        ④execute(Prams…)必须在UI线程上调用。
        ⑤不要手动调用onPreExecute(), onPostExecute(), doInBackground(), onProgressUpdate()。
        ⑥不能在doInBackground(Params… params)中更改UI界面

     4.AsyncTask异步任务代码实现进度条

       • MainActivity.java

package com.steven.myasynctask;
 
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
 
public class MainActivity extends Activity {
 
    private DownloadTask task;
    private Button button;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = (Button) findViewById(R.id.btn_start);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                task = new DownloadTask(MainActivity.this);
                //该task只能被执行一次,否则多次调用时将会出现异常
                task.execute();
            }
        });
    }
}

       • DownloadTask.java

package com.steven.myasynctask;
 
import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
 

public class DownloadTask extends AsyncTask {
    ProgressBar pb;
    TextView tvProgress;
    int progress = 0;
    protected Context context;
 
    public DownloadTask(Activity activity) {
        context = activity;
        pb = (ProgressBar) activity.findViewById(R.id.progress_bar);
        tvProgress = (TextView) activity.findViewById(R.id.tv_progress);
    }
 
    //子线程中运行,耗时操作。将执行结束的结果返回onPostExecute()参数中
    @Override
    protected Boolean doInBackground(Void... params) {
        while (true) {
            //更新进度信息,回调onProgressUpdate函数
            publishProgress(progress);
            if (progress != 100) {
                progress += 10;
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                return true;
            }
        }
    }
 
    //运行在UI线程中,任务执行前的准备,比如弹出进度条
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pb.setVisibility(View.VISIBLE);
    }
 
    //运行在UI线程中,执行处理返回的结果
    @Override
    protected void onPostExecute(Boolean aBoolean) {
        super.onPostExecute(aBoolean);
        if (aBoolean) {
            Toast.makeText(context, "下载完毕", Toast.LENGTH_SHORT).show();
            pb.setVisibility(View.INVISIBLE);
        }
    }
 
    //运行在UI线程中,更新当前进度条信息。被publishProgress调用
    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        pb.setProgress(progress);
        tvProgress.setText(progress + "%");
    }
}

       • activity_main.xml



 
    
 
        
 
        
    
 
    
 
    

       • 效果图

总结

     AsncyTask适合处理一些简单的异步任务,然而对于比较复杂的或多个同时存在异步任务,还是使用Thread+Handler异步消息机制更加方便和清晰。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/750271.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号