OnBind()调用得太早了

时间:2015-07-15 01:29:23

标签: android android-service android-service-binding

我遇到一个问题,即当我的服务类中的活动调用startService()并跟随bindService()导致NPE @ onBind()时,因为我的线程可能尚未完成初始化。在这种情况下,我如何保证locationThreandMessengeronBind()触发之前就已准备就绪。

xxx服务类

public class xxx extends Service {

    private static final String TAG = "xxx";
    private Messenger locationThreadMessenger;
    private LocationThread locationThread;

    private void onWorkPrepared() {
        locationThreadMessenger = new Messenger(locationThread.mHandler);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return locationThreadMessenger.getBinder();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        isNewThreadNecessary();
        return START_STICKY;
    }

    private void isNewThreadNecessary() {
        if (locationThread != null) {
            if (locationThread.isAlive()) {
                Log.i(TAG, "Thread is alive...");
            } else {
                Log.i(TAG, "Thread was reused...");
                locationThread.start();
            }
        } else {
            Log.i(TAG, "Initializing new Thread...");
            locationThread = new LocationThread("Thread");
            locationThread.start();
        }
    }

    private class LocationThread extends HandlerThread {

        private static final String TAG = "Thread";

        private Handler mHandler;

        public LocationThread(String name) {
            super(name);
        }

        @Override
        protected void onLooperPrepared() {
            super.onLooperPrepared();
            mHandler = new Handler(getLooper()) {
                @Override
                public void handleMessage(Message msg) {

                }
            };
            onWorkPrepared();
            Log.i(TAG, "Thread started...");
        }
    }
}

2 个答案:

答案 0 :(得分:0)

我不知道这是不是一个好习惯(我肯定不会)。但是现在这是我的修复。它可以在不冻结UI的情况下工作

{{1}}

答案 1 :(得分:0)

您可以尝试wait()notify(),但如果您的onLooperPrepared()需要一段时间,那么您可以获得ANR,因为服务在主线程上运行。

@Override
public IBinder onBind(Intent intent) {
    if (locationThreadMessenger == null) {
    synchronized (locationThread)
    {
         locationThread.wait();
    } 
    }
    return locationThreadMessenger.getBinder();
}

private class LocationThread extends HandlerThread {

    private static final String TAG = "Thread";

    private Handler mHandler;

    public LocationThread(String name) {
        super(name);
    }

    @Override
    public void run()
    {
        Log.i(TAG, "run");
        Looper.prepare();
        synchronized (this)
        {
            mHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {

                }
            };
            onWorkPrepared();
            Log.i(TAG, "run after onWorkPrepared");
            notify();
        }
        Looper.loop();

    }
}