博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
android多线程
阅读量:4916 次
发布时间:2019-06-11

本文共 5152 字,大约阅读时间需要 17 分钟。

线程的基本用法:

android多线程编程其实并不比java多线程特殊,基本都是使用相同的语法,比如说,定义一个线程只需要新建一个类继承自Thread,然后重写父类的run()方法,并在里面编写耗时的逻辑即可,

public class MyThread extends Thread {    @Override    public void run() {        //处理具体的逻辑        super.run();    }}

如何启动这个线程,其实也很简单,只需要new出MyThread的实例,然后调用它的start()方法,这样run()方法中的代码就会在子线程当中运行了。

new MyThread().start();

使用继承的方式耦合性有点高,更多的时候我们都会选择使用Runnable接口的方式定义一个线程

public class MyThread implements Runnable{    @Override    public void run() {        //处理具体的逻辑    }}

如果使用了这种写法,启动线程的方法也需要进行相应的改变,

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

当然如果不想专门再定义一个类去实现runnable接口,也可以使用匿名累的方式,如下所示:

Thread thread= new Thread(new Runnable() {       @Override       public void run() {           //具体处理逻辑       }   }).start();

再子线程中更新UI

和许多其他GUI库一样,安卓的UI也是线程不安全的,也就是说,如果想要更新应用程序里的UI元素,则必须在主线程中进行,否则就会出现异常。

下面我们来看一个例子:

    
public class MainActivity extends Activity  implements View.OnClickListener {   private  TextView textView;    private Button changeText;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        textView=(TextView)findViewById(R.id.text1);        changeText=(Button)findViewById(R.id.change_text);        changeText.setOnClickListener(this);    }    @Override    public void onClick(View v) {        switch (v.getId()){            case R.id.change_text:            new Thread(new Runnable() {                @Override                public void run() {                    textView.setText("Nice to neet you");                }            }).start();                break;            default:                break;        }    }

运行的时候会出现如下图所示的情况:

由此正式了安卓确实是不允许自线程中运行UI操作,但是有时候我们必须在子线程里面去执行一些耗时任务,然后根据任务的执行结果来更新相应的UI控件,

安卓提供了一套异步消息处理机制完美的解决了在子线程中运行UI操作。

首先我们先来看一下这个解决的代码

public class MainActivity extends Activity  implements View.OnClickListener {   private  TextView textView;    private Button changeText;    public  static  final  int UPDATE_TEXT=1;    private  Handler handler=new Handler() {        @Override        public void close() {                    }        @Override        public void flush() {        }        @Override        public void publish(LogRecord record) {        }        public  void  handleMessage(Message msg){            switch (msg.what){                case  UPDATE_TEXT:                    textView.setText("Nice to meet you");                    break;                default:                    break;            }        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        textView=(TextView)findViewById(R.id.text1);        changeText=(Button)findViewById(R.id.change_text);        changeText.setOnClickListener(this);    }    @Override    public void onClick(View v) {        switch (v.getId()){            case R.id.change_text:            new Thread(new Runnable() {                @Override                public void run() {                    Message message=new Message();                    message.what=UPDATE_TEXT;                    handler.sendMessage(message);                                    }            }).start();                break;            default:                break;        }    }

我们来解析异步消息处理机制:

安卓中的异步消息处理主要由四部分组成,Message,Handler,MessageQueue和Looper。

1 Message

Message是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。

2 Handler

Handler故名思义也就是处理者的意思,它主要是用于发送和处理消息的,发送消息一般是使用Handler的sendmessage()方法,而发出的消息经过一系列地辗转处理后,最终会传递到Handler地handleMessage()方法中,

3MessageQueue

MessageQueue 是消息队列的意思,它主要用于存放所有通过Handler发送的消息,这部分消息会一直存在于消息队列中,等待被处理,每个线程中只会有一个MessageQueue对象。

4 Looper

Looper是每个线程中的MessageQueue的管家,调用Looper的loop()方法后,就会进入到一个无限循环当中,然后每当发现MessageQueue中存在一条消息,就会将它取出,并传递到Handler的handleMessage()方法中,每个线程中也只会只有一个Looper对象。

首先需要在主线成中创建一个Handler对象,并重写handleMessage()方法,然后子线程中需要进行UI操作时,就创建一个Message对象,并通过Handler将这条消息发送出去,之后这条消息会被添加到MessageQueue的队列中等待被处理,而Looper则会一直尝试从MessageQueue中取出待处理消息,最后奋发回Handler的handleMessage()方法中,由于Handle是在主线程中创建的,所以此时handleMessage()方法中的代码也会在主线成中运行,于是我们在这里就可以安心的运行UI操作,整个异步消息处理的核心思想就是这样。

为了更加方便我们在自线程中对UI进行操作,android还提供了另外的一些好用的工具,AsyncTask就是其中之一,借助AsyncTask,即使你对异步消息处理机制完全不了解,也可以十分简单的从子线程切换的主线程,AsyncTask背后的实现原理也是基于异步消息处理机制的。

由于AsyncTask是一个抽象类,所以如果我们想要使用它,就必须创建一个子类去继承它,在继承AsyncTask类指定三个范性参数,这三个参数的用途如下:

1 params

在执行AsyncTask时需要传入参数,用于在后台任务中使用。

2progress

后台任务执行时,如果需要在界面上显示当前的进度,则使用这里指定的范性作为进度单位。

3 result

当任务执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回类型。

我们还需要自定义一些方法才能完成对任务的定制。

1 onPreExecute()

这个方法会在后台任务开始执行之前调用,用于进行一些界面上的初始化操作,比如显示一个进度条对话框

2 doInBackground(Params...)

这个方法中所有代码都会在自线程中运行,我们应该在这里去处理所有的耗时任务,任务一旦完成就可以通过return语句来将任务的执行结果返回,如果AsyncTask的读三个泛型参数指定的是void,就可以不返回任务执行结果,注意,在这个方法中是不可以进行ui操作的,如果要更新UI元素,比如说反馈当前任务的执行进度,可以调用publishProgress(Progress...)方法来完成。

3 onProgressUpdate(Progress...)

  当在后台任务中调用了publishprogress(progress...)方法后,这个方法就会很快被调用,方法中携带的参数就是在后台任务传递过来的,在这个方法中可以对UI进行操作。利用参数中的数值就可以对界面元素进行相应的更新。

4 onPostExecute(Result)

当后台任务执行完毕并通过return语句进行返回时,这个方法就很快会被调用,返回的数据会作为位参数传递到此方法中,可以利用返回的数据来进行一些UI操作,比如说提醒任务执行的结果以及关闭掉进度条对话框。

如果要启动的话只需要调用其execute()方法。

 

转载于:https://www.cnblogs.com/aizhiyuan/p/5321844.html

你可能感兴趣的文章
Linux中crond服务与crontab用法
查看>>
PLSQL连接ORACLE配置字符串简介 oracle网络配置 三个配置文件 listener.ora、sqlnet.ora、tnsnames.ora原理解释...
查看>>
分享8年开发经验,浅谈个人发展经历,明确自己发展方向
查看>>
开发使用Node.js的一个小技巧
查看>>
Mike的农场 BZOJ4177
查看>>
IT职场人生系列
查看>>
如何指定个别属性进行transition过渡
查看>>
Python爬虫基础--分布式爬取贝壳网房屋信息(Client)
查看>>
jmeter(十二)关联之正则表达式提取器
查看>>
win7系统复制文件到u盘提示文件过大怎么办
查看>>
The path "" is not valid path to the gcc binary.
查看>>
KMP算法
查看>>
NBUT [1369] A Breaking Computer
查看>>
SonarQube4.4+Jenkins进行代码检查实例之三-单元測试分析
查看>>
【转载】appium自动化环境搭建
查看>>
jsp编译、执行过程
查看>>
NOIP2017游记
查看>>
关于js的在ie和Firefox的差别
查看>>
node-webkit无边框窗口用纯JS实现拖动改变大小
查看>>
Extjs grid combo
查看>>