简体   繁体   English

取消注册后,Android广播接收器不会立即处理广播而导致错误

[英]android broadcast receiver doesn`t instantly process broadcast caused a bug after been unregistered

I registered Broadcast receiver when uploading photos via network. 通过网络上传照片时,我注册了广播接收器。 Each time uploading a photo successfully, the method broadcasts message to Broadcast Receiver. 每次成功上传照片时,该方法都会向广播接收器广播消息。 When Broadcast Receiver receives the message, it will add a cache to local database. 广播接收器收到消息后,它将向本地数据库添加缓存。 I use this logic to ensure no duplicate photos upload. 我使用此逻辑来确保没有重复的照片上传。

Until now everything is alright, but when I stop uploading photos (actually photo uploading logic was implemented by Service ), the onDestory() method was invoked and I unregisterd the Broadcast Receiver there and that makes the problem happen. 到现在为止,一切都还不错,但是当我停止上传照片时(实际上,照片上传逻辑是由Service实施的),调用了onDestory()方法,并在那里取消注册了广播接收器,这导致了问题的发生。

As we know the broadcast message has some delay time, though one photo was successfully uploaded, did not ensure that Broadcast Receiver instantly add the cache to database on its onReceive() method. 众所周知,尽管成功上传了一张照片,广播消息仍有一定的延迟时间,但并不能确保广播接收器立即通过其onReceive()方法将缓存添加到数据库中。 If BR did not handle the cache quickly, it may lose the chance to do because when onDestroy() was called, system will unregisterd Broadcast Receiver and the message will be ignored. 如果BR无法快速处理缓存,则可能会失去这样做的机会,因为调用onDestroy()时,系统将取消注册广播接收器,并且消息将被忽略。 So there will be one cache missed, and the local database will lack of one cache to ensure no duplicate photos to be uploaded. 因此,将丢失一个缓存,并且本地数据库将缺少一个缓存,以确保没有重复的照片要上传。

code segment one 代码段一

@Override
public void onCreate() {
    Intent bIntent = new Intent(this, TransferService.class);
    bindService(bIntent, mConnection, Context.BIND_AUTO_CREATE);        
    LocalBroadcastManager.getInstance(this).registerReceiver(transferReceiver,
            new IntentFilter(TransferService.BROADCAST_ACTION));
}


@Override
public void onDestroy() {
    if (mTransferService != null) {
        unbindService(mConnection);
        mTransferService = null;
    }
    LocalBroadcastManager.getInstance(this).unregisterReceiver(transferReceiver);
}

code segment two 代码段二

private BroadcastReceiver transferReceiver = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
        if (mTransferService == null) {
            return;
        }

        String type = intent.getStringExtra("type");
        if (type == null) {
            return;
        }
        if (type.equals(TransferService.BROADCAST_FILE_UPLOAD_SUCCESS)) {
            int taskID = intent.getIntExtra("taskID", 0);
            UploadTaskInfo info = mTransferService.getUploadTaskInfo(taskID);

            if (info != null) {
                cUploadManager.onPhotoUploadSuccess(info.repoName,
                        info.repoID, info.localFilePath
                                .substring(info.localFilePath
                                        .lastIndexOf(DIR)));
            }
        }

    }

};

click here to view the complete source code 点击这里查看完整的源代码

So anyone can give some advice to go through this problem, since broadcast receiver caused off by one bug, do I need to change to use handler instead? 因此,任何人都可以提出一些建议来解决此问题,因为广播接收器是由一个错误引起的,我是否需要更改为使用处理程序? ? waiting for your advice, and thanks! 等待您的建议,谢谢!

It is because the transfer service here is multi-thread, which means once the thread was started by main thread, the main thread lost control of it. 这是因为此处的传输服务是多线程,这意味着一旦线程由主线程启动,主线程便失去了对其的控制。 So you can not track the uploading status. 因此,您无法跟踪上传状态。 Even user already turned off the upload service, destroy the BroadcastReceiver, the sub-thread can still exist and continue to upload. 即使用户已经关闭了上传服务,销毁了BroadcastReceiver,子线程仍然可以存在并继续上传。 Obliviously, to use the BroadcastReceiver to add cache, it will definitely lose one cache. 显然,要使用BroadcastReceiver添加缓存,肯定会丢失一个缓存。

The bug above was caused by the BroadcastReceiver can not ensure that it always process the broadcast message (add cache to local db) because it will be destroyed by main thread when sub-thread still exist and continue to send broadcast. 上面的错误是由BroadcastReceiver无法确保始终处理广播消息(将缓存添加到本地db)引起的,因为当子线程仍然存在并继续发送广播时,它将被主线程破坏。

the solution here is to add cache in sub-thread itself. 解决方案是在子线程本身中添加缓存。 When finished uploading (upload state is FINISHED) then add a cache inside the sub-thread. 上传完成后(上传状态为FINISHED),然后在子线程内添加缓存。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM