Android学习笔记10-Service后台服务(一)-Android 多线程编程
1,Service简介
Service时Android程序中的四大组件之一,它和Activity都是Context的子类,只不过Service没有UI界面,是在后台运行的组件。
Service是Android平台中实现程序后台运行的解决方案,非常适合去执行那些不需要和用户交互而且还要长期运行的任务,服务的运行不依赖于任何界面,即使程序被切换到后台。或者用户打开了其他的程序,服务依然能够保持正常的运行。
注意:
- 服务依赖于创建服务时所在的应用程序进程,不是运行在一个独立的进程中。
- 当一个应用程序被杀掉时,依赖于该程序的服务也会停止运行。
- 服务并不会自动开启线程,所有的代码都是默认运行在主线程中,也就是我们需要在服务的内部手动创建子线程,并在这里执行具体的任务。
2,Android多线程编程
在Android程序中,当我们需要执行一些比较耗时的操作,比如发起一条网络请求,考虑到网络可能比较满的原因,服务器可能不会立刻响应我们的请求,如果不将这些操作放到子线程中运行,就会导致主线程堵塞。
2.1线程的基本使用方法
1, 第一种方式
然后通过new MyThread.start().启动,这样代码就会在子线程中运行了。2,第二种启动方式 ,通过继承Runnable接口的方式定义一个线程。
然后通过
启动。
3,第三种方式
2.2在子线程中更新UI
在Android中,UI是属于线程不安全的,如果想更新UI元素,必须在主线程中更新。
下面举一个在子线程中更新UI的DEMO。
activity_main.xml 布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/change_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Change text" />
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="hello world"
android:textSize="20sp" />
</RelativeLayout>
定义了两个控件,一个button,一个TextView,我们要实现当点击button的时候,改变TextView的显示内容。
在点击事件的函数中,定义一个子线程进行UI操作,运行一下程序会发现崩溃。
所以,在Android中不允许在子线程中对UI进行操作。
Android中提供了一套异步消息处理机制,完美的解决了在子线程中进行UI操作的问题.
package com.example.chen.androidthread;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private TextView text;
public static final int UPDATE_TEXT = 1;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATE_TEXT:
//在这里可以进行UI操作
text.setText("Nice to meet you");
break;
default:break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//声明控件
Button changeText = (Button) findViewById(R.id.change_text);
text = (TextView) findViewById(R.id.text);
//设置点击监听器
changeText.setOnClickListener(this);
}
/**
* 设置点击事件
*/
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.change_text:
Message message = new Message();
message.what = UPDATE_TEXT;
handler.sendMessage(message);
break;
default:break;
}
}
}
在这里,我们并没有在子线程中更新UI,而是创建了一个Message(android.os.Message) 对象,通过设置message的what为指定值UPDATE_TEXT.然后通过handler的sendMessage() 方法将message发送出去。
在Handler类中,在重写的handleMessage(Message msg) 方法中,会接受sendMessage()方法发送来的message对象。接着,对message的what值进行判断,如果是UPDATE_TEXT,就会执行更新UI的操作。
点击button
在这个demo中,我们熟悉了Android异步处理消息的基本方法,在下篇文章中,我们来来了解了解Android异步处理消息的工作机制