我已经准备了一个非常简单的测试用例1个活性2个片段对我的问题:
- MainActivity.java (存储选择的项目中共享偏好)
- MyMainFragment.java (显示一个文本视图和“选择”按钮)
- MyListFragment.java (显示项目列表)
最初MainActivity显示MyMainFragment。
当用户触摸“选择项...”按钮,MainActivity显示MyListFragment有:
public void selectedButtonClicked() {
SharedPreferences prefs = getSharedPreferences(PREFS, 0);
int index = prefs.getInt(INDEX, -1);
Fragment fragment = MyListFragment.newInstance(index);
getFragmentManager().beginTransaction()
.addToBackStack(null)
.replace(R.id.root, fragment, LIST)
.commit();
}
用户触摸,MainActivity存储所选择的项目的位置在共享偏好列表中的项目中的一个,并调用后popBackStack()
再次显示MyMainFragment:
public void itemSelected(int index) {
SharedPreferences prefs = getSharedPreferences(PREFS, 0);
Editor editor = prefs.edit();
editor.putInt(INDEX, index);
editor.commit();
getFragmentManager().popBackStack();
// How to show the index in mSelectedTextView?
}
即在我的应用程序在MainActivity完成所有的“繁重的工作”:它会显示1 2的片段,并保持在共享偏好的用户数据。
我的问题是:如何在显示所选项目(在上面的截图“项目07”) mSelectedTextView
的MyMainFragment的?
我正在寻找一种方式来做到这一点正确,没有任何黑客(例如片段应不能触及共享偏好)。
更新:我已经尝试通过corsair992的建议(感谢!)
public void itemSelected(int index) {
SharedPreferences prefs = getSharedPreferences(PREFS, 0);
Editor editor = prefs.edit();
editor.putInt(INDEX, index);
editor.commit();
getFragmentManager().popBackStackImmediate();
MyMainFragment f = (MyMainFragment) getFragmentManager().findFragmentById(R.id.root);
// call a method in MyMainFragment to update mSelectedTextView
f.setText("Selected index: " + index);
}
但它仅适用,当用户在触摸MyListFragment的项目。 但是,它没有工作,当用户返回触摸返回按钮MyMainFragment。
在我看来,你已经有了一个合理的第一部分答案(由corsair992建议 - 从选择的项目传递值),第二部分是你如何处理返回键。
有这样做(听回栈等),但我用最fequently就是其中的几种方法:
声明一个返回键监听器接口:
public interface BackKeyListener {
boolean onBackPressed();
}
在主要活动添加以下内容:
import BackKeyListener;
void onBackKeyPressed() {
boolean backKeyHandled = false;
Fragment activeFragment = getActiveFragment();
if (activeFragment instanceof BackKeyListener) {
backKeyHandled = ((BackKeyListener) activeFragment).onBackKeyPressed();
}
if (!handled) {
// If should process back key normally, pass to super..
super.onBackKeyPressed();
}
}
Fragment getActiveFragment() {
// I'm assuming you place all your fragments here, if not..
// alter to suit
return getFragmentManager().findFragmentById(R.id.root);
}
在MyListFragment添加以下内容:
import BackKeyListener;
class MyListFragment extends Fragment(orsomething) implements BackKeyListener
public boolean onBackPressed() {
// User pressed back, select default item..
((MainActivity) getActivity()).itemSelected(selectedItem);
// In this case, prevent normal back processing or
// you might get a double backstack pop.
return true;
}
使用的片段的界面让你“不小心”的活性片段是什么。 如果它实现了BackKeyListener,按下返回键时,在MainActivity将调用它。 这给你传递一个值回活动的选项。
是您的第一个片段仍然保存在内存中,当发生这种情况? 我认为如此。 这意味着你可以使用一个SharedPreferences.OnSharedPreferenceChangeListener 。 只是要MyMainFragment实现接口,然后使用registerOnSharedPreferenceChangeListener
监视更改。 不要忘了注销,但!
一个更好的想法可能是注册您的活动作为听众,并使其通过这些数据来MyMainFragment当它再次显示它。
首先,你可以使用SharedPrefences
UI线程内,即内部片段。 这个通常的误解扎根从时间时,只有commit()
方法。 现在,我们已经apply()
以异步方式运行,并get*()
使用缓存的数据。
其次,要解决你的问题,而不SDK杂耍最简单的方法,将是你的第二个片段来通知项目选择的活动(例如,您的片段内: ((MainActivity)getActivity()).setSelectedItem(itemId);
)并获得该值在你的第一个片段的onResume()
例如, ((MainActivity)getActivity()).getSelectedItem();
)。 当然,你应该检查在被选择的情况下没有什么空此值。
分配标签MyMainFragment,假定这将是MY_MAIN_FRAGMENT_TAG。 此代码添加到您的itemSelected
方法:
Fragment myMainFragment = getFragmentManger.findFragmentByTag("MY_MAIN_FRAGMENT_TAG");
if (null != myMainFragment) {
Bundle args = new Bundle();
myMainFragment.getArguments().putInt("selectedItem", index);
getFragmentManager().popBackStack();
}
然后在你的MyMainFragment覆盖onViewStateRestored()方法:
@Override
public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
mSelectedTextView.setText(String.valueOf(getArguments.getInt("selectedItem")));
}
也许你会需要一些额外的检查,如果null != getArguments()
并设置apropriate价值为TextView
。
一种解决方案是使用setTargetFragment / getTargetFragment方法。 通过这种方法,您可以使用只是你没有碎片的活动和SharedPreferences帮助。 在你MyMainFragment,当用户点击按钮“选择项...”你可以用你的回调selectedButtonClicked()为:
public void selectedButtonClicked() {
Fragment fragment = MyListFragment.newInstance(index);
//Set the TargetFragment
fragment.setTargetFragment(MyMainFragment.this, MyListFragment.REQUESTCODE)
getFragmentManager().beginTransaction()
.addToBackStack(null)
.replace(R.id.root, fragment, LIST)
.commit();
}
你必须定义MainFragment回调onActivityResult:
public void onActivityResult(int requestCode, int resultCode, Intent data){
if(requestCode == MyListFragment.REQUESTCODE){
f.setText("Selected index: " + intent.getInt("INDEX");
}
}
在MyListFragment一旦用户选择一个项目,你可以调用你的回调itemSelected()
public void itemSelected(int index) {
Intent i = new Intent();
i.putExtraInt("INDEX",index);
getTargetFragment.onActivityResult(MyListFragment.REQUESTCODE,Context.Result_OK,i);
getFragmentManager().popBackStackImmediate();
}
文章来源: How to pass selected item from ListFragment to previous Fragment after calling popBackStack()?