Android学习-多线程基础介绍

来源:互联网 发布:2017年好听的网络歌曲 编辑:程序博客网 时间:2024/06/06 12:52

android的多线程编程与java差不多相同,基本都是使用相同的语法。

1.创建一个线程并启动

第一种:

新建一个类继承thread类重写父类的run()方法

class Mythread extends Thread{    @override    public void run(){}}

启动:new MyThread().start();

第二种:

第一种方法耦合性高,一般选用第二种方法,实现Runnable接口。

class MyThread implements Runnable{@override    public void run(){}}

启动方法如下:
MyThread myThread=new Mythread();
new Thread(myThread()).start();
Thread的构造函数接收了一个Runnable参数。
也可使用匿名类的方式实现:

new Thread(new Runnable()){@override    public void run(){}}

2.在子线程中更新UI

Android的UI是线程不安全的。想要更新程序里的UI元素,则必须在主线程中进行。
android提供了一套异步处理机制,解决了在子线程中更新UI的问题。
首先在activity_main.xml文件中创建一个简单的按钮,对应的MainActivity中的代码修改成如下:

public class MainActivity extends AppCompatActivity implements View.OnclickListener{    public static final int UPDATE_TEXT=1;    privite TextView text;    private Handler handler=new Handler(){    public void handleMesseage(Message msg){        switch(msg.what){            case UPDATE_TEXT:            //在这里可进行UI操作            text.setText("nice to meet u");            break;            default:            break;        }    }};...@Overridepublic void onClick(View v){    switch(v.getId()){        case R.id.change_text:            new Thread(new Runnable(){                Message m=new Message();                m.what=UPDATE_TEXT;                handler.sendMessage(m);//将message对象发出去            }).start();            break;        default:            break;    }}}

创建一个Message(android.os.Message)对象,Handler的sendMessage()把Message发送出去,在handleMessage中进行处理。
Android的异步处理消息主要由4部分组成:Message,Handler,MessageQueue和Looper.
Message
主要在线程之间传递消息,可以携带少量的信息,用于不同线程之间的数据交换。有what(字符串),arg1,arg2(整形数据),obj(携带object对象)
Handler
主要用于发送sendMessage和处理handleMessage消息
MessageQueue
是消息队列的意思,主要用于存放所有通过Handler发送的消息,这部分消息一直存在队列中,等待被处理。每个线程只会有一个MessageQueue对象。
Looper
是每个线程中的MessageQueue的管家,调用Looper的loop方法后,就会进入到一个无线循环中,没放发现MessageQueue中存在一个消息,就会取出,并传递到Handler的handleMessage()的方法中。每个线程只会有一个Looper对象。

3.使用AsyncTask

用AsyncTask工具来实现消息的异步处理,比较方便。
AsyncTask是一个抽象类,想要使用必须要建一个类去继承他,继承的时候可以为AsyncTask类指定三个泛型参数:
Params
在执行AsyncTask时,需要传入的参数,可用于在后台任务中的使用。
Progress
后台任务执行时,如果需要在上面显示当前的进度,则使用这里指定的泛型作为进度单位。
Result
当前任务执行完成后,如果需要对结果进行返回,则使用这里指定的泛型作为返回的类型。
一个最简单的定义AsyncTask可以写成如下方式:

class DownloadTask extends AsyncTask<Void,Integer,Boolean>{...}

实际用到的时候,经常需要重写的有以下四个方法:
(1).onPreExecute()
会在后台任务开始执行之前调用,用于一些界面的初始化操作。比如显示一个进度条对话框。
(2).doInBackground(Params…)
所有代码都是在子线程中运行,一般用于处理耗时的任务,一旦完成,就可以通过return语句来将任务的执行结果返回,如果AsyncTask的第三个参数为void则不返回。在这个方法中是不可以进行UI操作的,如果需要更新UI,则可以publishProgress(Progress…)的方法来完成。
(3).onProgressUpdate(Progress…)
当后台调用了publishProgress(Progress…),onProgressUpdate(Progress…)方法很快就会被调用,该方法携带的参数就是后台传递过来的,在这个方法中可以对UI进行操作,利用参数中的数值就可以对界面元素进行相应的更新、。
(4).onPostExecute(Result)
后台任务执行完毕后看,通过return进行返回,这个方法就很快会被调用,返回的数据作为参数传递到此方法中,可以利用返回的数据进行一些UI操作。比如:提醒任务执行的结果,以及关掉进度条对话框等。

一个比较完整的自定义的AsyncTask就可以写成如下方式:

class DownloadTask extends AsynsTask <void,Integer,Boolean>{    @Override    protected void onPreExcute(){    progressDialog.show();//显示进度对话框    }    @Override    protected Boolean doInBackground(){     try{         while(true){             int downloadPerent=doDownload(Void...params);             publishProgress(downloadPercent);             if(downloadPercent>=100){                 break;             }         }     }catch(Exception e){         return false;     }    return true;    }    @Override    protected void onProgressUpdate(Integer...values){                  progressDialog.setMessage("Downloaded"+values[0]+"%");    }     @Override    protected void onPostExecute(Boolean result){        progressDialog.dismiss();//关闭进度对话框        //在这里提示下载结果        if(result){            Toast.makeText(context,"Downed succeded",Toast.LENGTH_SHORT).show();        }else{        Toast.makeText(context,"Downed failed",Toast.LENGTH_SHORT).show();        }    }}

总结:doInBackground()方法中执行具体的耗时任务,onProgressUpdate()方法进行UI操作,onPostExecute()执行一些收尾的工作。
想要启这个任务执行以下的代码:
new DownloadTask().excute();

原创粉丝点击