简体   繁体   English

BroadcastReceiver onReceive 方法在 Fragment onCreate() 之前调用

[英]BroadcastReceiver onReceive method called before Fragment onCreate()

I have an IntentService which starts when SplashActivity onCreate called:我有一个 IntentService,它在 SplashActivity onCreate 调用时启动:

class SplashActivity : AppCompatActivity() {

    private val handler = Handler(Looper.getMainLooper())

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_splash)
        startService(Intent(applicationContext, ContactsService::class.java))
        handler.postDelayed({
            val intent = Intent(this, MainActivity::class.java)
            startActivity(intent)
        }, SPLASH_DELAY.toLong())
    }
}

private const val SPLASH_DELAY = 1500

Here is my IntentService:这是我的 IntentService:

override fun onHandleIntent(intent: Intent?) {
        val cursor = ContactUtil.getContactsCursor(null, null, this)
        val contacts = ContactUtil.getContacts(cursor, this)
        cursor?.close()
        val contactsIntent = Intent(CONTACTS_RECEIVER)
        contactsIntent.putParcelableArrayListExtra(CONTACTS, ArrayList<Parcelable>(contacts))
        sendBroadcast(contactsIntent)
    }

1 - If I have huge number of contacts, my broadcastReceiver onReceive method called after Fragment creation, which is ok. 1 - 如果我有大量的联系人,我的 broadcastReceiver onReceive方法会在 Fragment 创建后调用,这没关系。

2 - If I have a few number of fragment, onReceive method called before Fragment creation, which does not update my UI at all. 2 - 如果我有几个片段,在片段创建之前调用onReceive方法,它根本不会更新我的 UI。

private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            List<Contact> contacts = intent.getParcelableArrayListExtra(CONTACTS);
            mContacts = contacts;
            mAdapter.setItems(contacts, true);
            mProgressBar.setVisibility(View.GONE);
            mAppBarLayout.setVisibility(View.VISIBLE);
            mRecyclerView.setVisibility(View.VISIBLE);
        }
    };

What is the solution for 2nd case?第二种情况的解决方案是什么?

Start by getting rid of the system broadcast.首先摆脱系统广播。 Assuming your code does what is described, you are leaking all the user's contacts to every single app on the device .假设您的代码执行所描述的操作,则您将所有用户的联系人泄露给设备上的每个应用程序 So, beyond the performance problems and the chance of crashing the app with a too-big Intent , you have a major privacy hole.因此,除了性能问题和使用太大Intent导致应用程序崩溃的可能性之外,您还有一个重大的隐私漏洞。

Then, get rid of the IntentService .然后,摆脱IntentService It is deprecated, and it is unnecessary if all you are doing with this data is using it in a UI.它已被弃用,如果您对这些数据所做的一切都是在 UI 中使用它,那么它是不必要的。

Instead, set up a singleton repository that manages your access to the contacts.相反,设置一个 singleton 存储库来管理您对联系人的访问。 Have your activity's ViewModel call some method on the repository to do that, where the repository uses an ordinary background thread (perhaps through an Executor or RxJava type).让您的活动的ViewModel调用存储库上的某个方法来执行此操作,其中存储库使用普通后台线程(可能通过Executor或 RxJava 类型)。 The repository can emit an event when the work is completed, such as via LiveData or RxJava.存储库可以在工作完成时发出事件,例如通过LiveData或 RxJava。 Your ViewModel can use LiveData for letting the UI layer know about the data so it can update the UI.您的ViewModel可以使用LiveData让 UI 层了解数据,以便它可以更新 UI。 And, since LiveData is a value holder, it will hold the value even if the value arrives before the fragment is ready for it.而且,由于LiveData是一个值持有者,即使值在片段准备好之前到达,它也会持有该值。

This approach (repository object with a reactive API) is part of Google's general architecture recommendations.这种方法(具有反应式 API 的存储库 object)是 Google 通用架构建议的一部分。

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

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