`
我要阳光
  • 浏览: 60232 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

Android Service 常见误区

阅读更多
学习了一下Service,网上常见的一些就不说了,说一下感觉容易给人造成误解的地方

1. 如Service的创建都是在新进程创建的么?
其实不是的,在 Dev Guide中写道:
引用

Caution: A service runs in the main thread of its hosting process—the service does not create its own thread and does not run in a separate process (unless you specify otherwise). This means that, if your service is going to do any CPU intensive work or blocking operations (such as MP3 playback or networking), you should create a new thread within the service to do that work. By using a separate thread, you will reduce the risk of Application Not Responding (ANR) errors and the application's main thread can remain dedicated to user interaction with your activities.

就是说,当创建一个Service的时候,默认是在Application的进程里主UI线程创建的,如果你在Service中进行阻塞的操作,会直接阻塞UI线程,可能导致五秒无响应的提醒,所以官方建议是在Service里面创建新的线程来防止阻塞放生。

2. 如何在新进程里创建Service?
一般的方法就是在manifast中声明Service的时候,使用process标签,注明所使用的进程,默认使用当前程序主进程:
<service 
    android:name="org.foreal.MusicServiceTest"
    android:enabled="true" 
    android:process=":music_process"
></service>

其中如果进程的名字时以 ":"开头的,说明进程是当前程序的私有进程,其他程序无法访问,如果是以小写字母开头的进程,说明进程是一个全局的进程,多个程序都可访问此进程,达到多程序共享进程的目的。

3.如果不用新进程的Service,如何方便的进行一些阻塞操作?
可以继承IntentService来编写自己的Service,IntentService会自动创建一个worker thread,来进行操作如:
public class MyIntentService extends IntentService {
    
    private final static String TAG = "MyIntentService"; 

    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.i(TAG, "onHandleIntent");
        
        try {
            synchronized (this){
                wait(3000);
            }
            Log.i(TAG, "完成一次");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

其中只需要重写onHandleIntent方法来处理自己的操作就行,其中每一次的操作都会进去队列中,按顺序串行执行。
其中要注意的是,IntentService在执行完队列中所有操作以后会自动销毁当前Service,也就是说,如果你onHandleIntent中是个非阻塞操作的话,很可能每次调用结束以后Service都被销毁,然后下次在建立新的Service。
此类可以很方便的完成大多数工作,但是如果要进行并发操作的Service,此类就不适合,应自己实现。

3. 如何使Service私有?
如果在Service中声明intent filter,那么其他程序也可以通过你声明的intent filter来访问你的Service,为了避免这种情况,首先你可以去掉intent filter,每次调用Service都使用Intent(Context, Class)的形式,但是,如果喜欢用intent filter的形式,可以使用exported标签,来使Service私有,这样即使定义intent filter,其他程序也无法访问。

4.如果一个Service在startService以后 又进行了bindService那么他的生命周期是怎样的,stopService能否结束掉Service?
答案是不能的,如果一个Service进行了bind操作,那么再进行stopService是无法结束掉此Service,知道绑定的Context全部结束,或解除绑定,Service才会被结束。

5. Service 中Onstart方法中,参数startid是什么意思,又有什么用处?
因为在使用startService开启一个Service以后,必须手动的关闭Service,所以Service可能自己调用 stopSelf 方法,来在任务完成的时候结束掉自己。
但是这个时候就会出现一个问题,如果startService调用了2次,那么就执行了两次onStart操作,在第一次onStart操作结束以后,Service可能会认为任务已经完成,并结束掉自己,这个时候第二次的onStart可能还没结束,导致了任务还未完成就被强行关闭了。
而startid代表当前onStart被调用的一个编号,在结束Service时候,调用stopSelf(startid),这样Service就可以检查,此startid是否是最近一次调用的,如果是,那么才结束Service,否则不结束。

如有错误,欢迎指出探讨。
0
1
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics