我正在编写一个使用NFC来读取存储在其上的数据的应用程序。我的应用程序使用Fragments和Fragment没有onNewIntent()方法。因为,我正在阅读的数据是通过处理NFC相关操作的单独类来完成的,我唯一需要做的就是更新Fragment中的TextView。但是,此实现也可用于将新Intent传递给Fragment。
这是我当前使用接口的实现。在收到新的Intent并且NFC相关检查成功后,我正在呼叫监听器。这是托管Fragment的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 Fragment,其中包含需要在读取NFC时需要更新的TextView:
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);
}
}
这段代码完全像我的应用程序预期的那样,但是,我想知道是否有更好的方法来处理碎片中的新Intent?
答案 0 :(得分:2)
这是一个老问题,但是如果有人碰到它,让我回答一下。
首先,您的代码中存在错误:
您无法像Fragments
那样在Activity
内注册Activity
作为听众。原因是系统可以销毁Fragments
和Activity
,然后从保存的状态重新创建(请参阅Recreating an Activity上的文档)。发生这种情况时,将创建Fragment
和Fragment
的新实例,但将onNewBalanceRead()
设置为侦听器的代码将无法运行,因此Activity
将永远不会被打电话这是Android应用程序中非常常见的错误。
为了传达从Fragment
到Fragment
的事件,我发现至少有两种可能的方法:
基于界面:
有an officially recommended approach for communication between Fragments。这种方法与您现在使用的方法类似,它使用Activity
或Activity
实现的回调接口,但它的缺点是紧密耦合和许多丑陋的代码。
基于事件总线:
更好的方法(恕我直言)是利用事件总线 - "主要组件" (在您的情况下为Fragment
)帖子"更新"事件到事件总线,而"从属组件" (在您的情况下为onStart()
)将自己注册到onStop()
中的事件总线({{1}}中的注销)以接收这些事件。这是一种更清洁的方法,它不会在通信组件之间添加任何耦合。
我的所有项目都使用Green Robot's EventBus,但我无法推荐它。
答案 1 :(得分:0)
至少有一种选择:来自Activity.onNewIntent documentation:
在接收新意图之前,活动将始终暂停,因此您可以指望在此方法之后调用onResume()。
请注意,getIntent()仍会返回原始的Intent。您可以使用setIntent(Intent)将其更新为此新Intent。
FragmentActivity.onNewIntent documentation不同,但我认为这与上述陈述相矛盾。我还假设Fragment.onResume将在FragmentActivity.onResume之后调用,尽管文档对我来说似乎有些挑剔,尽管我的测试证实了这个假设。基于此,我在活动中更新了Intent(Kotlin中的示例)
override fun onNewIntent(intent: Intent?) {
setIntent(intent)
super.onNewIntent(intent)
}
在Fragment.onResume中,我可以像这样处理新的意图
override fun onResume() {
super.onResume()
doStuff(activity.intent)
}
通过这种方式,活动不需要知道它所拥有的片段。
答案 2 :(得分:-2)
不,没有更好的方法。片段可以比活动更长寿,并且根本不一定与它们相关联,因此提供新的意图是没有意义的。
顺便说一下,你的代码中有一些错误:)
if (actionBar.getSelectedNavigationIndex() != 1) {
魔术数字很糟糕!使用常数。
if (myBalanceBundle == null)
myBalanceBundle = new Bundle();
myBalanceBundle.putString(Keys.BALANCE.toString(), balance);
actionBar.setSelectedNavigationItem(1);
我们已经知道导航项目设置为1
} else {
newBlanceListener.onNewBalanceRead(balance);
添加空检查。用户可能从未选择过导航项。