在处理片段onNewIntent(Handling onNewIntent in Fragment)

2019-07-21 19:10发布

我写了使用NFC读取储存在它的一些数据的应用程序。 我的应用程序使用的碎片和碎片不附带onNewIntent()方法。 因为,我读的数据与我单独的类,它处理NFC相关的操作来完成,我需要做的唯一的事情就是更新片段内TextView的。 然而,这也实现可以使用新的意图传递给片段。

这是我目前的执行,这使得使用的接口。 收到后新的意向和NFC相关的检查成功,我呼吁听众。 这是它承载片段FragmentActivity。

public class Main extends FragmentActivity implements
    ActionBar.OnNavigationListener {

private Bundle myBalanceBundle;
private NFC nfcObj;
private NewBalanceListener newBlanceListener;

@Override
public void onNewIntent(Intent intent) {
    setIntent(intent);
}

@Override
protected void onResume() {
    getNFCState();
    super.onResume();
}

private void getNFCState() {
    //Other NFC related codes
    else if (nfc_state == NFC.NFC_STATE_ENABLED){
        readNFCTag();
    }
}

private void readNFCTag() {
    //Other NFC related codes
    if (getIntent().getAction().equals(NfcAdapter.ACTION_TECH_DISCOVERED)) {
        nfcObj.setTag((Tag) getIntent().getParcelableExtra(
                NfcAdapter.EXTRA_TAG));
        nfcObj.readQuickBalance();

        transitQuickReadFragment(nfcObj.getCurrentBalance());
    }
}

private void transitQuickReadFragment(String balance) {
    // Creates a balance bundle and calls to select MyBalance Fragment if it
    // is not visible. Calls listener is it is already visible.
    if (actionBar.getSelectedNavigationIndex() != 1) {
        if (myBalanceBundle == null)
            myBalanceBundle = new Bundle();

        myBalanceBundle.putString(Keys.BALANCE.toString(), balance);

        actionBar.setSelectedNavigationItem(1);
    } else {
        newBlanceListener.onNewBalanceRead(balance);
    }
}

@Override
public boolean onNavigationItemSelected(int position, long id) {
    // Other fragment related codes
    fragment = new MyBalance();
    fragment.setArguments(myBalanceBundle);
    newBlanceListener = (NewBalanceListener) fragment;
    // Other fragment related codes
}

// Interface callbacks. You can pass new Intent here if your application
// requires it.
public interface NewBalanceListener {
    public void onNewBalanceRead(String newBalance);

}
}

这是应查看mybalance片段,其具有的TextView需要每当NFC读取进行更新:

public class MyBalance extends Fragment implements NewBalanceListener {

private TextView mybalance_value;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    //Other onCreateView related code

    Bundle bundle = this.getArguments();
    if (bundle != null)
        mybalance_value.setText(bundle.getString(Keys.BALANCE.toString(),
                "0.00"));
    else
        mybalance_value.setText("0.00");

    //Other onCreateView related code
}

@Override
public void onNewBalanceRead(String newBalance) {
    mybalance_value.setText(newBalance);
}
}

此代码工作完全像预期为我的应用程序,但是,我想知道是否有更好的方式来处理来自片段新意图是什么?

Answer 1:

这是一个老问题,但让我回答这个问题的情况下,任何人碰到它。

首先,你必须在你的代码中的错误:

你不能注册Fragments作为内听众Activity ,你做的方式。 其原因是, ActivityFragments可以由系统被破坏,后来从保存的状态重新创建(见文档重新创建的活动 )。 发生这种情况时,双方的新实例ActivityFragment将被创建,但设置的代码Fragment作为听者将无法运行,因此onNewBalanceRead()将永远不会被调用。 这是Android应用程序很常见的错误。

为了从事件通信Activity ,以Fragment我看到至少有两种可能的方法:

接口基于:

有一个官方推荐的片段之间的通信方式 。 这种方法类似于现在,它使用由两种实现的回调接口做什么FragmentActivity ,但其缺点是紧耦合和许多丑陋的代码。

事件总线基于:

更好的办法(恕我直言)是利用事件总线的- “主组件”( Activity你的情况)的帖子“更新”事件,事件总线,而“从组件”( Fragment在你的情况)将自己注册到事件总线onStart()在注销onStop()以接收这些事件)。 这是一种清洁的方法,其不增加通信的部件之间的任何耦合。

我所有的项目中使用的绿色机器人的EventBus ,我不能建议高度不够。



Answer 2:

至少有一个选择:从Activity.onNewIntent文档 :

活动将一直接收到新的意图前被暂停,所以你可以指望的onResume()这个方法之后被调用。

需要注意的是getIntent()仍返回原来的意图。 您可以使用setIntent(意向)将其更新到这个新的意图。

FragmentActivity.onNewIntent文件是不同的,但我不认为它违背了上述声明。 我也作出这样的假设Fragment.onResume之后将被称为FragmentActivity.onResume ,即使文档似乎有点挑剔我,虽然我的测试中证实了这一假设。 在此基础上我更新了意图在活动像这样(在科特林例子)

override fun onNewIntent(intent: Intent?) {
    setIntent(intent)
    super.onNewIntent(intent)
}

而在Fragment.onResume我能胜任,像这样的新意图

override fun onResume() {
    super.onResume()
    doStuff(activity.intent)
}

这样的活动并不需要知道什么碎片它持有。



Answer 3:

没有,有没有更好的办法。 片段可以活得比较长的活动,而不一定依赖于他们在所有所以提供了新的意图就没有意义。

顺便说一句,你在你的代码中的一些错误:)

if (actionBar.getSelectedNavigationIndex() != 1) {

幻数是坏的! 使用常量。

    if (myBalanceBundle == null)
        myBalanceBundle = new Bundle();

    myBalanceBundle.putString(Keys.BALANCE.toString(), balance);
    actionBar.setSelectedNavigationItem(1);

我们已经知道,navigationitem设置为1

} else {
    newBlanceListener.onNewBalanceRead(balance);

添加一个空检查。 用户可能从来没有选择的导航项目。



文章来源: Handling onNewIntent in Fragment