Thread和AsyncTask使用:

来源:互联网 发布:linux查看光纤卡流量 编辑:程序博客网 时间:2024/05/31 13:16

1.Thread使用:
继承Thread类:

public class MyThread extends Thread {    @Override    public void run() {        //线程中处理的逻辑    }}

调用:

new MyThread().start();

实现Runnable:

public class MyThread implements Runnable {    @Override    public void run() {        //线程中处理的逻辑    }}

调用:

        MyThread myThread=new MyThread()        new Thread(myThread).start();

异步消息处理

public class ThreadTestActivity extends Activity {    private TextView text;    private Handler handler=new Handler(){        @Override        public void handleMessage(Message msg) {            switch (msg.what){                case 0:                    //子线程不允许操作UI.,在这里操作UI 防止线程堵塞                    text.setText("这里操作UI,防止线程堵塞");                    break;                case 1:                    break;                default:                    break;            }        }    };    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Button button=findViewById(R.id.start_download);        text=(TextView)findViewById(R.id.text_view);        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                new Thread(new Runnable() {                    @Override                    public void run() {                        Message message=new Message();                        message.what=0;                        handler.sendMessage(message);                    }                }).start();            }        });    }}

1.Message存储少量数据,用于进程间交换数据。除了what字段,还有arg1 arg2 以及obj.

2.Handler处理Message发送过来的信息,发送消息一般是Handler的sedMessage()方法。最终会传递到Handler的Handler的handleMessage()方法中。

3.MessageQueue是存放Handler的sendMessage()发送过来的消息,这些消息存在一个队列中,等待被处理。每个线程中只有一个MessageQueue对象。

4.Loop:MessageQueue的管家,调用Loop的loop()方法后,就会无线循环。没发现MessageQueue中存在消息队列,就会从中取出,传递到Handler的handleMessage()中。每个线程中只有已给Loop对象

runOnUiThread()方法就是这个原理实现的

2.AsyncTask使用:

继承AsyncTask,实现一个抽象方法 doInBackground()

public class MyAsyncTask extends AsyncTask<String,Integer,Integer> {    @Override    protected Integer doInBackground(String... strings) {        return null;    }}

Params:执行AsyncTask时需要传入的参数,可用于在后台任务
Progress:界面上显示当前进度,只用这里指定泛型作为进度单位
Result:当任务执行完,需要对结果进行返回,可以指定泛型作为返回值类型

一些常用方法:
onPreExecute()
这个会在执行后台任务之前被调用,常用语一些初始化操作

doInBackground(Params…)
这个方法的代码都会在子线程中执行,常用的耗时操作都在这里执行,可以通过reture返回执行结果。AsyncTask的第三个参数指定为Void,则可以不返回任务执行结果。如果需要操作UI,比如反馈当前任务进度。可以调用publishProgress(Progress…)

onProgressUpdata(Progress..)
调用 publishProgress()方法后,onProgressUpdata()方法会很快被调用,这个方法携带过来的参数就是在后台任务传递过来的,可以利用参数中的数值进行UI操作

onPostExecute(Result…)
后台执行完毕通过return返回结果时,就会调用此方法,doInBackground()返回的结果会作为参数传递到此方法中,比如提醒任务执行结果

例子:DownloadTask.java代码

public class DownloadTask extends AsyncTask<String, Integer, Integer> {    public static final int TYPE_SUCCESS = 0;    public static final int TYPE_FAILED = 1;    public static final int TYPE_PAUSED = 2;    public static final int TYPE_CANCELED = 3;    private DownloadListener listener;    private boolean isCanceled = false;    private boolean isPaused = false;    private int lastProgress;    public DownloadTask(DownloadListener listener) {        this.listener = listener;    }    @Override    protected Integer doInBackground(String... params) {        InputStream is = null;        RandomAccessFile savedFile = null;        File file = null;        try {            long downloadedLength = 0; // 记录已下载的文件长度            String downloadUrl = params[0];            String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/"));            String directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();            file = new File(directory + fileName);            if (file.exists()) {                downloadedLength = file.length();            }            long contentLength = getContentLength(downloadUrl);            Log.d("TAG", "contentLength: "+contentLength);            if (contentLength == 0) {                return TYPE_FAILED;            } else if (contentLength == downloadedLength) {                // 已下载字节和文件总字节相等,说明已经下载完成了                return TYPE_SUCCESS;            }            OkHttpClient client = new OkHttpClient();            Request request = new Request.Builder()                    // 断点下载,指定从哪个字节开始下载                    .addHeader("RANGE", "bytes=" + downloadedLength + "-")                    .url(downloadUrl)                    .build();            Response response = client.newCall(request).execute();            if (response != null) {                is = response.body().byteStream();                savedFile = new RandomAccessFile(file, "rw");                savedFile.seek(downloadedLength); // 跳过已下载的字节                byte[] b = new byte[1024];                int total = 0;                int len;                while ((len = is.read(b)) != -1) {                    if (isCanceled) {                        return TYPE_CANCELED;                    } else if(isPaused) {                        return TYPE_PAUSED;                    } else {                        total += len;                        savedFile.write(b, 0, len);                        // 计算已下载的百分比                        int progress = (int) ((total + downloadedLength) * 100 / contentLength);                        publishProgress(progress);                    }                }                response.body().close();                return TYPE_SUCCESS;            }        } catch (Exception e) {            e.printStackTrace();        } finally {            try {                if (is != null) {                    is.close();                }                if (savedFile != null) {                    savedFile.close();                }                if (isCanceled && file != null) {                    file.delete();                }            } catch (Exception e) {                e.printStackTrace();            }        }        return TYPE_FAILED;    }    @Override    protected void onProgressUpdate(Integer... values) {        int progress = values[0];        //更新下载进度        if (progress > lastProgress) {            listener.onProgress(progress);            lastProgress = progress;        }    }    @Override    protected void onPostExecute(Integer status) {        switch (status) {            case TYPE_SUCCESS:                listener.onSuccess();                break;            case TYPE_FAILED:                listener.onFailed();                break;            case TYPE_PAUSED:                listener.onPaused();                break;            case TYPE_CANCELED:                listener.onCanceled();            default:                break;        }    }    public void pauseDownload() {        isPaused = true;    }    public void cancelDownload() {        isCanceled = true;    }     /**     * 获取文件总字节数     * @param downloadUrl     * @return contentLength     * @throws IOException     */    private long getContentLength(String downloadUrl) throws IOException {        OkHttpClient client = new OkHttpClient();        Request request = new Request.Builder()                .url(downloadUrl)                .build();        Response response = client.newCall(request).execute();        if (response != null && response.isSuccessful()) {            long contentLength = response.body().contentLength();            response.close();            return contentLength;        }        return 0;    }}

DownloadListener.java代码

public interface DownloadListener {    void onProgress(int progress);    void onPaused();    void onCanceled();    void onSuccess();    void onFailed();}

DownloadService.java代码

public class DownloadService extends Service {    private String downloadUrl;    private DownloadTask downloadTask;    private DownloadListener downloadListener=new DownloadListener() {        @Override        public void onProgress(int progress) {            getNotificationManage().notify(1,getNotification("download...",progress));        }        @Override        public void onPaused() {            downloadTask=null;            Toast.makeText(DownloadService.this,"Paused Download",Toast.LENGTH_LONG).show();        }        @Override        public void onCanceled() {            downloadTask=null;            stopForeground(true);            Toast.makeText(DownloadService.this,"Canceled Download",Toast.LENGTH_LONG).show();        }        @Override        public void onSuccess() {            downloadTask=null;            //前台服务关闭,并创建一个下载成功通知            stopForeground(true);            getNotificationManage().notify(1,getNotification("下载完成",-1));            Toast.makeText(DownloadService.this,"Download success",Toast.LENGTH_LONG).show();        }        @Override        public void onFailed() {            downloadTask=null;            //下载失败关闭前台服务通知,并创建一个下载失败通知            stopForeground(true);            getNotificationManage().notify(1,getNotification("Download Failed",-1));            Toast.makeText(DownloadService.this,"Download failed",Toast.LENGTH_LONG).show();        }    };    private DownloadBind mBind=new DownloadBind();    class DownloadBind extends Binder{        public void startDownload(String url){            if (downloadTask==null){                DownloadTask downloadTask=new DownloadTask(downloadListener);                downloadUrl=url;                downloadTask.execute(downloadUrl);                startForeground(1,getNotification("download...",0));                Toast.makeText(DownloadService.this,"download...",Toast.LENGTH_LONG).show();            }        }        public void pauseDownload(){            if (downloadTask!=null){                downloadTask.pauseDownload();            }        }        public void cancelDownload(){            if (downloadTask!=null){                downloadTask.cancelDownload();            }else {                if (downloadUrl!=null){                    //取消下载,删除文件,关闭通知                    String fileName=downloadUrl.substring(downloadUrl.lastIndexOf("/"));                    String fileDir= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();                    File file=new File(fileDir+fileName);                    if (file.exists()){                        file.delete();                    }                    getNotificationManage().cancel(1);                    stopForeground(true);                    Toast.makeText(DownloadService.this,"Cancel download",Toast.LENGTH_LONG).show();                }            }        }    }    @Override    public IBinder onBind(Intent intent) {        return mBind;    }    public NotificationManager getNotificationManage(){       return (NotificationManager) getSystemService(NOTIFICATION_SERVICE);    }    private Notification getNotification(String title,int progress){        Intent intent=new Intent(this,MainActivity.class);        PendingIntent pi=PendingIntent.getActivity(this,0,intent,0);        NotificationCompat.Builder builder=new NotificationCompat.Builder(this);        builder.setContentTitle(title).setSmallIcon(R.mipmap.ic_launcher).setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher));        builder.setContentIntent(pi);        if (progress>0){            builder.setContentTitle(progress+"%");            builder.setProgress(100,progress,false);        }        return builder.build();    }}

DownloadService服务中实现DownloadListener中的5个方法,onProgress()方法中创建通知栏,在下拉状态栏中实时更新下载进度。onSuccess()方法中关闭前台任务,创建一个新通知告诉用户下载完成了。
DownloadBind中提供三个方法 分别分别用于启动,暂停,和取消下载任务。startDownload()方法中实例了DownloadTask,并调用了execute()方法开启下载。这个下载服务就作为已给前台服务运行了startForeground()方法在系统状态栏创建持续运行通知

MainActivity.java代码

public class MainActivity extends AppCompatActivity implements View.OnClickListener {    private Button startBtn, pauseBtn, cancelBtn;    private DownloadService.DownloadBind downloadBind;    private ServiceConnection connection = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {            downloadBind = (DownloadService.DownloadBind) iBinder;        }        @Override        public void onServiceDisconnected(ComponentName componentName) {        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        startBtn = (Button) findViewById(R.id.start_download);        pauseBtn = (Button) findViewById(R.id.pause_download);        cancelBtn = (Button) findViewById(R.id.cancel_download);        startBtn.setOnClickListener(this);        pauseBtn.setOnClickListener(this);        cancelBtn.setOnClickListener(this);        Intent intent = new Intent(MainActivity.this, DownloadService.class);        startService(intent);//启动服务        bindService(intent, connection, BIND_AUTO_CREATE);//绑定bind        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {            ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);        }    }    @Override    public void onClick(View view) {        if (downloadBind == null) {            return;        }        switch (view.getId()) {            case R.id.start_download:                String url = "https://raw.githubusercontent.com/guolindev/eclipse/master/eclipse-inst-win64.exe";                String url2="http://sw.bos.baidu.com/sw-search-sp/software/71bdb07e88935/Firefox-55.0.2.6435-setup.exe";                downloadBind.startDownload(url2);                break;            case R.id.pause_download:                downloadBind.pauseDownload();                break;            case R.id.cancel_download:                downloadBind.cancelDownload();                break;            default:                break;        }    }    @Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {        switch (requestCode) {            case 1:                if (grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {                    Toast.makeText(this, "拒绝权限将无法使用程序", Toast.LENGTH_SHORT).show();                    finish();                }                break;            default:        }    }    @Override    protected void onDestroy() {        super.onDestroy();        unbindService(connection);    }}

layout布局文件就不贴出来了,感觉已经写了很长了。
在onCreatView()中启动服务,和bindService()绑定service.
ServiceConnection 中实例了DownloadBind。有了DownloadBind的实例就可以调用其中的StartDownload(),pauseDownload(),cancelDownload()三个方法了。分别对应到不同按钮的点击事件中。
另外则是一个权限的动态申请了。

原创粉丝点击