您的位置:首页 > 移动开发 > Android开发

Android开发,后台service与前台activity通信

2016-03-15 14:56 711 查看
android开发,在处理耗时操作的时候,不能再UI(主线程)中处理,有些人为了方便,直接在activity中new 一个新的线程来处理耗时任务,虽然可以达到目的,但是线程不好控制,使用不当可能会导致严重的性能问题。那么如何处理这些耗时的操作呢。

其实android里面的四大组件里面的Service就可以很好的解决这一问题,service和activity差不多,只不过activity是运行在前台,有界面的,而Service是运行在后台的没有界面的。

在activity里面,我们可以通过startService方法打开一个Service,这个Service用来处理比如下载图片,下载文件等等比较耗时的操作。

比如我要下载一个网络文件,并且想要知道下载的进度,通过这个例子,给出几种Service和activity之间通信的方法:

效果图:







方法一:

MainActivity.class

package com.example.wangluo.intentservice;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.Toast;

public class MainActivity extends Activity implements View.OnClickListener {

private Button button;

private ProgressBar progressBar;

private MyHandler handler;

private ServiceConnection serviceConnection;

private MainService mainService;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

button = (Button) findViewById(R.id.button);

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

handler = new MyHandler();  //初始化handler

//初始化ServiceConnection对象,实现两个回调方法
serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//和service连接上时, 会执行此方法
//绑定成功后,会返回一个IBinder对象, 我们通过这个IBinder对象可以得到Service的实例
mainService = ((MainService.MyBind) service).getService();

//将handler对象传递给service,让handler实现service和activity的通信
mainService.setHandler(handler);
}

@Override
public void onServiceDisconnected(ComponentName name) {

//和service断开连接时, 执行此方法
}
};

//绑定service
Intent intent = new Intent("android.intent.action.MainService");
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);

init();

}

public void init () {

button.setOnClickListener(this);

}

@Override
public void onClick(View v) {

switch (v.getId()) {

case R.id.button:

//使用Service 暴露出来的方法,下载文件
mainService.downLoadFile();
break;

}

}

@Override
protected void onDestroy() {
super.onDestroy();

//Activity销毁的时候, 将service和Activity解绑
unbindService(serviceConnection);

}

class MyHandler extends Handler {

@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);

//将handler传递过来的message,赋值在progressBar上,动态显示进度条
progressBar.setProgress(Integer.valueOf(msg.obj.toString()));

//下载完成,解除绑定,提示用户下载完成
if (100 <= Integer.valueOf(msg.obj.toString())) {

//解除绑定
unbindService(serviceConnection);

//Toast下载完成
Toast.makeText(MainActivity.this, "下载完成", Toast.LENGTH_SHORT).show();

}

}
}

}


MainService.class

package com.example.wangluo.intentservice;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.annotation.Nullable;

/**
* Created by wangluo on 2016/3/15.
*/
public class MainService extends Service {

private static final int MAX_FILE_SIZE = 100;   //文件大小

private int defaultSize = 0;    //从0开始下载文件

private MyThread thread;    //下载文件的线程

private Handler handler;    //用于Service 和 Activity来通信的对象

//向外暴露接口,用来传入handler对象
public void setHandler (Handler handler) {

this.handler = handler;

}

@Nullable
@Override
public IBinder onBind(Intent intent) {
return new MyBind();
}

public class MyBind extends Binder {

public MainService getService() {
return MainService.this;
}

}

public void downLoadFile() {

//从0开始下载
defaultSize = 0;

thread = new MyThread();    //new 一个MyThread对象

thread.start(); //开启线程,下载文件
}

class MyThread extends Thread {
@Override
public void run() {
super.run();

//模拟文件下载,每次每秒加10
while (defaultSize < MAX_FILE_SIZE) {

defaultSize += 10;

Message message = new Message();    //message 对象

try {
Thread.sleep(1000); //睡眠1秒

message.obj = defaultSize;
handler.sendMessage(message);   //handler传递message

} catch (InterruptedException e) {
e.printStackTrace();
}

}

}
}

}


AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.wangluo.intentservice">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<service android:name=".MainService">
<intent-filter>
<action android:name="android.intent.action.MainService" />
</intent-filter>
</service>

</application>

</manifest>


方法一是使用handler实现Service与activity的通信。在activity中绑定Service,拿到Service的实例,然后调用Service的下载文件的方法。

方法二:IntentService 和 activity的通信

MainActivity.java

package com.example.wangluo.broadcastreceiver;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.Toast;

public class MainActivity extends Activity implements View.OnClickListener {

private Button button;

private ProgressBar progressBar;

private MyReceiver receiver;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

button = (Button) findViewById(R.id.button);

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

receiver = new MyReceiver();

IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.intent.action.MyReceiver");

//注册广播接收器
registerReceiver(receiver, intentFilter);

init();

}

public void init () {

button.setOnClickListener(this);

}

@Override
protected void onDestroy() {
super.onDestroy();
//注销广播接收器
unregisterReceiver(receiver);
}

@Override
public void onClick(View v) {

switch (v.getId()) {

case R.id.button:

//开启service,下载文件
Intent intent = new Intent("android.intent.action.MyIntentService");

startService(intent);

break;

}

}

class MyReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {

int progress = intent.getIntExtra("progress", 0);
progressBar.setProgress(progress);

if (progress >= 100) {

Toast.makeText(MainActivity.this, "下载完成", Toast.LENGTH_SHORT).show();
}
}
}

}


MyIntentService.java

package com.example.wangluo.broadcastreceiver;

import android.app.IntentService;
import android.content.Intent;
import android.util.Log;

/**
* Created by wangluo on 2016/3/15.
*/
public class MyIntentService extends IntentService {

private static final String TAG = "MyIntentService";

private static final int MAX_FILE_SIZE = 100;

private int defaultSize = 0;

/**
* Creates an IntentService.  Invoked by your subclass's constructor.
*/
public MyIntentService() {
super("MyIntentService");
}

@Override
protected void onHandleIntent(Intent intent) {

downLoadFile();
}

//下载文件的方法
private void downLoadFile() {

Log.e(TAG, "****downLoadFile****");

while (defaultSize < MAX_FILE_SIZE) {

try {
defaultSize += 10;

Thread.sleep(1000);

//发送广播,把进度传过去
Intent intent = new Intent();
intent.setAction("android.intent.action.MyReceiver");
intent.putExtra("progress", defaultSize);
sendBroadcast(intent);

} catch (InterruptedException e) {
e.printStackTrace();
}

}

}

}


AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.wangluo.broadcastreceiver">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<service android:name=".MyIntentService">
<intent-filter>
<action android:name="android.intent.action.MyIntentService" />
</intent-filter>
</service>
</application>

</manifest>


方法二使用IntentService与activity通信,使用IntentActivity的好处是,代码更简洁,不用new一个新的线程,因为IntentService运行在一个单独的线程里面,而Service使用运行在应用的主线程里面的。第一种方法不能直接在Service里面执行耗时操作,因为它本身就在主线程里面,而主线程里面不能执行耗时的操作,所以还得新开一个线程去执行耗时的操作,IntentService是不用的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: