一、线程间通信
1、Handler
AndroidUI线程不安全,想要更新UI需在主线程中进行,否则会出现异常,Handler机制就是把复杂的处理工作交给子线程完成,然后子线
程通过Handler对象通知主线程,由主线程更新UI
Handler机制最根本目的在于解决多线程并发问题,如果采用加锁处理将导致性能下降
sendMessage()使用方法
-新增Handler对象,并重写handleMessage方法
-在子线程中创建Message对象,指定字段传递数据(也可使用Handler对象的obtainMessage()方法循环使用Message对象)
-调用Handler对象的sendMessage()方法传递Message对象
-在handleMessage()中取出数据,改变UI(也可使用Message对象的sendToTarget()返回)
public class MainActivity extends AppCompatActivity {
private TextView textView;
private int UPDATE_TEXT = 1;
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(msg.what == UPDATE_TEXT){
textView.setText("CHANGE");
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.tv);
}
public void doClick(View view){
new Thread(new Runnable() {
@Override
public void run() {
Message message = new Message();
message.what = UPDATE_TEXT;
handler.sendMessage(message);
}
}).start();
}
}
指定Callback截获消息
public class MainActivity extends AppCompatActivity {
private TextView textView;
private Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
textView.setText("Change");
Toast.makeText(MainActivity.this , "已改变" , Toast.LENGTH_SHORT).show();
return true;//false 不截获 true 截获
}
}){
public void handleMessage(Message msg) {
Toast.makeText(MainActivity.this , "已发送" , Toast.LENGTH_SHORT).show();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.tv);
}
public void doClick(View v){
Message message = handler.obtainMessage();
message.sendToTarget();
}
}
post()使用方法
-新增Handler对象
-调用Handler对象的post(Runnable)方法
-在子线程中改变UI
public class MainActivity extends AppCompatActivity {
private TextView textView;
private Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.tv);
}
public void doClick(View view){
handler.post(new Runnable() {
@Override
public void run() {
textView.setText("CHANGE");
}
});
}
}
sendMessageDelayed()&postDelayed()使用方法
-创建Handler对象
-创建Runnable对象
-重写run()方法,改变UI并调用Handler对象的postDelayed(Runnable , long)方法,实现递归
-在主线程调用Handler对象的postDelayed(Runnable , long)方法
-调用Handler对象的removeCallbacks(Runnable)方法,停止循环
public class MainActivity extends AppCompatActivity {
private TextView textView;
private int i = 0;
private Handler handler = new Handler();
Runnable runnable = new Runnable() {
@Override
public void run() {
textView.setText("CHANGE" + (i++));
handler.postDelayed(runnable , 1000);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.tv);
handler.postDelayed(runnable , 1000);
}
}
2、异步消息处理机制
Message:在线程间传递的消息,内部可携带少量信息,除what字段,还可使用arg1,arg2携带整形数据,使用obj字段携带Object对象
Hnadler:用于发送和处理消息
MessageQueue:用于存放Handler发送的消息,这些消息会一直存放在MessageQueue中,等待被处理,每个线程中只有一个 MessageQueue
Looper:调用其loop()方法后就会进入无限循环中,每当发现MessageQueue存在一条消息,就会取出并传递到handleMessage()中, 每个线程中只有一个Looper
3、AsyncTask
AsyncTask为Android提供的工具类,便于我们在子线程中对UI进行操作
使用方法
-创建子类继承自AsyncTask类,并指定三个泛型参数
Params:参数,可用于在后台任务中使用
Progress:当前进度
Result:返回值
-构建子类回调方法
doInBackground():必须重写,异步执行后台线程将要完成的任务
onPreExecute():执行后台耗时操作前调用,完成一些初始化操作
onProgressUpdate():在doInBackground()中调用publishProgress()方法更新任务进度后,触发该方法
onPostExecute():当doInBackground()完成后,系统自动调用onPostExecute()方法,并将doInBackground()返回值传给该方法
-在UI线程中创建AsyncTask子类实例,并调用AsyncTask子类实例的execute()执行异步加载(不能多次调用)
-调用AsyncTask子类实例的cancel(boolean)方法设置取消异步加载状态标志,在具体操作中使用isCancelled()判断异步加载是否被
public class ImageTest extends Activity {
private ImageView imageView;
private ProgressBar progressBar;
private DownloadTask mTask = new DownloadTask();
private String URL = "https://img-my.csdn.net/uploads/201504/12/1428806103_9476.png";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image);
imageView = (ImageView) findViewById(R.id.imageView);
progressBar = (ProgressBar) findViewById(R.id.pro);
//执行异步加载
mTask.execute(URL);
}
@Override
protected void onPause() {
super.onPause();
if(mTask != null && mTask.getStatus() == AsyncTask.Status.RUNNING){
mTask.cancel(true);
}
}
class DownloadTask extends AsyncTask {
@Override
protected void onPreExecute() {
super.onPreExecute();
progressBar.setVisibility(View.VISIBLE);
}
@Override
protected Bitmap doInBackground(String... params) {
String url = params[0];
URLConnection urlConnection;
InputStream is;
Bitmap bitmap = null;
try {
urlConnection = new URL(url).openConnection();
is = urlConnection.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
for(int i = 0;i < 100;i ++){
if(isCancelled()){
break ;
}
publishProgress(i);
Thread.sleep(100);
}
bitmap = BitmapFactory.decodeStream(bis);
is.close();
bis.close();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return bitmap;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
if(isCancelled()){
return;
}
progressBar.setProgress(values[0]);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
progressBar.setVisibility(View.GONE);
imageView.setImageBitmap(bitmap);
}
}
}
二、进程间通信
1、AIDL概述
AIDL(Android Interface Definition Language)是一种接口定义语言,编译器通过.aidl文件的描述信息生成符合通信协议的java代码,通过这种方式可以完成进程间的通信工作
2、区别
AIDL IPC 多线程 多个应用程序
Binder 只有IPC 没有多线程 多个应用程序
Messenger 只有IPC 没有多线程
3、定义方式
可参考文档AndroidSDK/docs/guide/components/aidl.html
-Create the .aidl file
创建aidl文件,此文件会默认生成至aidl目录下
android studio需编译后才能生成对应java接口
AIDL默认支持的数据类型:
基本数据类型(除short)、String,CharSequence、List,Map(其中元素必须是支持的数据类型 ,且要求标记指示数据方向 in/out)、
Parcelable序列化
interface ICalculator {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
int add(int a1 , int a2);
}
-Implement the interface
自定义Service类继承Service
实现自定义aidl接口中的内部抽象类stub
public class IRemoteService extends Service {
@Override
public IBinder onBind(Intent intent) {
return iBinder;
}
private IBinder iBinder = new ICalculator.Stub(){
@Override
public int add(int a1, int a2) throws RemoteException {
return a1 + a2;
}
};
}
-Expose the interface to clients
实现自定义Service的onBind方法
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private EditText editText1 , editText2 , editText3;
private Button button;
private ICalculator iCalculator;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iCalculator = ICalculator.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
iCalculator = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText1 = (EditText) findViewById(R.id.et1);
editText2 = (EditText) findViewById(R.id.et2);
editText3 = (EditText) findViewById(R.id.et3);
button = (Button) findViewById(R.id.bt1);
button.setOnClickListener(this);
BindService();
}
@Override
public void onClick(View v) {
//ctrl+alt+m
int num1 = Integer.parseInt(editText1.getText().toString());
int num2 = Integer.parseInt(editText2.getText().toString());
try {
int res = iCalculator.add(num1 , num2);
editText3.setText(res + "");
} catch (RemoteException e) {
e.printStackTrace();
editText3.setText("ERROR");
}
}
private void BindService() {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.example.lenovo.aidl" , "com.example.lenovo.aidl.IRemoteService"));
bindService(intent , conn , Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn);
}
}
4、AIDL原理