android工作线程更新ui,Android Service——在子线程中更新UI

Android中的UI是线程不安全的,也就是说,如果要更新应用程序里的UI 元素,则必须在主线程中进行,否则就会出现异常。在这里介绍两个方法来解决这个问题

解析异步处理机制

Android中的异步消息处理主要分为四个部分,Message、Handler、MessageQueue、Looper。

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

2.Handler 顾名思义就是处理者的意思,它主要是用来发送和处理消息的。

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

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

定义一个点击事件,使得点击时,服务可以改变UI中的内容

package com.example.administrator.myhandlerapplication;

import android.app.Activity;

import android.os.Handler;

import android.os.Looper;

import android.os.Message;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.util.Log;

import android.view.Menu;

import android.view.MenuItem;

import android.view.View;

import android.widget.Button;

import android.widget.TextView;

public class MainActivity extends Activity {

public static final int UPDATE_TIME=1;

private int count=60;

private Button mButton;

private Button mButtonMainsend;

private TextView mTextView;

//定义一个内部类Handle

private Handler handler=new Handler(){

public void handleMessage(Message msg){

switch (msg.what){

case UPDATE_TIME

//在这里进行UI操作

String time= (String) msg.obj;

mButton.setText(time);

if (count>0){

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

//这里还可以简单的使用,对UI的操作在这里写,点击事件只需要发送一个空消息,然后在这里类似递归调用发送空消息,然后在这里对UI一次又一次的操作。即把count--放在handler中。

//handler.sendEmptyMessage(UPDATE_TIME);

}

break;

default:

break;

}

}

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mButton= (Button) findViewById(R.id.button_time);

mButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

new MyThread().start();

new Thread(new Runnable() {

@Override

public void run() {

while (count>0){

count--;

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

Message message=handler.obtainMessage(); //new Message();

message.obj=count+"秒";

message.what=UPDATE_TIME;

//发送Message对象

handler.sendMessage(message);

}

}

}).start();

}

});

}

}

先定义一个整型常量用来表示更新UI 中的内容的一个操作,然后新建一个Handler对象,并重写父类的handleMessage方法,然后对Message进行处理

这里是由子线程发送消息,由主线程来作相应处理,还可以通过主线程发送消息,然后子线程做相应处理,但是不常用。这里只是举例说明。

package com.example.administrator.myhandlerapplication;

import android.app.Activity;

import android.os.Handler;

import android.os.Looper;

import android.os.Message;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.util.Log;

import android.view.Menu;

import android.view.MenuItem;

import android.view.View;

import android.widget.Button;

import android.widget.TextView;

public class MainActivity extends Activity {

public static final int UPDATE_TIME=1;

private int count=60;

private Button mButton;

private Button mButtonMainsend;

private TextView mTextView;

//private Handler handler;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mButton= (Button) findViewById(R.id.button_time);

mButtonMainsend= (Button) findViewById(R.id.button_mainsend);

mButtonMainsend.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

//这个点击事件用来表示主线程发送消息,只是发送的是空消息,表示不进行任何操作

handler.sendEmptyMessage(UPDATE_TIME);

}

});

mButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

//这个按钮点击事件用来启动子线程。

new MyThread().start();

}

//这是子线程,等待接受主线程发送的消息,使用log打印来显示。

class MyThread extends Thread{

@Override

public void run() {

//super.run();

Looper.prepare();

handler=new Handler(){

@Override

public void handleMessage(Message msg) {

Log.d("11111111111111", "接收到主线程发来的消息");

}

};

Looper.loop();

}

}

}

在主线程中已经将Looper全部封装好所以不需要定义。而在子线程中需要将接收消息写在Looper的prepare()方法和loop()之间。

使用AsyncTask

Android还提供了AsyncTask抽象类来实现子类对UI进行操作。其实这个类实现原理也是基于消息处理机制,只是做了封装而已,通过几个方法来实现。

AsyncTask是一个抽象类,所以使用时需要创建一个子类去继承,继承时需要制定三个泛性值参数。

第一个参数Params ,在执行AsyncTask时需要传入的参数,可用于在后台任务中使用

第二个参数Progress ,在后台执行任务时,如果需要在界面上显示当前的进度,使用这里制定的泛型作为进度单位

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

继承自AsyncTask的类还需要重写其方法,其中经常需要重写的有四个方法

1.onPreExecute() 在后台任务开始执行之前调用,用于进行一些界面上的初始化操作。

2.doInBackground这个方法中的代码都会在子线程中运行,需要在这里处理所有的耗时操作任务。任务完后之后通过return语句来讲任务的执行结果返回,如果AsyncTask的第三个泛型制定的是Void,可以不返回任务执行结果。需要注意的是,在这个方法中是不可以进行UI操作的,如果需要更新UI 元素,可以调用publishProgress()方法来完成

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

4.onPostExecute(String s)当后台任务执行完毕并通过return语句进行返回时调用这个方法,返回的数据作为参数传递到这个方法中,可以利用返回的数据进行UI操作。

首先,定义一个按钮和一个进度条,通过按钮的点击事件启动后台服务,后台服务将信息发送回来显示到进度条上

android:id="@+id/progressBar"

android:layout_width="match_parent"

android:layout_height="wrap_content"

style="@style/Widget.AppCompat.ProgressBar.Horizontal"/>

android:id="@+id/button_sync"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="开始下载"/>

在MainActivity中声明一个类继承自AsyncTask并重写其方法,然后在按钮的点击事件中得到该类的一个对象,并可传参数给后台服务。

package com.example.administrator.masynctask;

import android.app.Activity;

import android.os.AsyncTask;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.view.Menu;

import android.view.MenuItem;

import android.view.View;

import android.widget.Button;

import android.widget.ProgressBar;

public class MainActivity extends Activity {

private int count=0;

private Button mButtonStart;

private ProgressBar mProgressBar;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mButtonStart= (Button) findViewById(R.id.button_sync);

mProgressBar= (ProgressBar) findViewById(R.id.progressBar);

mButtonStart.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

//得到一个AsyncTask的对象,这里需要传参数,所以为空

MyAsyncTask myAsyncTask=new MyAsyncTask();

myAsyncTask.execute();

}

});

}

class MyAsyncTask extends AsyncTask{

@Override

protected String doInBackground(Void... params) {

//进行后台操作

while (count<101){

count++;

publishProgress(count);

try {

Thread.sleep(200);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

return "下载完成";

}

@Override

protected void onPostExecute(String s) {

super.onPostExecute(s);

//利用doInBackground(Void... params)完成之后返回的值对UI 进行操作

mButtonStart.setText(s);

}

@Override

protected void onProgressUpdate(Integer... values) {

super.onProgressUpdate(values);

//利用doInBackground(Void... params)中publishProgress(count)传过来的值对UI中的进度条进行操作

mProgressBar.setProgress(values[0]);

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值