将片段的HashMap传递到bundle



我使用的是片段的backback的HashMap。为了保存背景和当前片段,我使用以下代码:

public class MainActivity extends AppCompatActivity {
private HashMap<String, Stack<Fragment>> mStacks;
public static final String TAB_PROFILE  = "tab_profile";
public static final String TAB_DASHBOARD  = "tab_dashboard";
public static final String TAB_CHATS  = "tab_chats";
public static final String TAB_SETTINGS  = "tab_settings";
private String mCurrentTab;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setupViews();
if (savedInstanceState != null) {
mCurrentTab = savedInstanceState.getString("currentTab");
mStacks = (HashMap<String, Stack<Fragment>>) savedInstanceState.getSerializable("stacks");
} else
selectedTab(TAB_DASHBOARD);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable("stacks", mStacks);
outState.putString("currentTab", mCurrentTab);
}
private void setupViews() {
mStacks = new HashMap<>();
mStacks.put(TAB_PROFILE, new Stack<>());
mStacks.put(TAB_DASHBOARD, new Stack<>());
mStacks.put(TAB_CHATS, new Stack<>());
mStacks.put(TAB_SETTINGS, new Stack<>());
BottomNavigationView bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_navigation);

bottomNavigationView.setSelectedItemId(R.id.action_dashboard);
BottomNavigationViewHelper.removeShiftMode(bottomNavigationView);

bottomNavigationView.setOnNavigationItemSelectedListener(item -> {
switch (item.getItemId()) {
case R.id.action_profile:
selectedTab(TAB_PROFILE);
return true;
case R.id.action_dashboard:
selectedTab(TAB_DASHBOARD);
return true;
case R.id.action_chats:
selectedTab(TAB_CHATS);
return true;
case R.id.action_settings:
selectedTab(TAB_SETTINGS);
return true;
}
return true;
});
bottomNavigationView.setOnNavigationItemReselectedListener(item -> {
if (mStacks.get(mCurrentTab).size() != 1) {
mStacks.get(mCurrentTab).clear();
switch (item.getItemId()) {
case R.id.action_profile:
selectedTab(TAB_PROFILE);
break;
case R.id.action_dashboard:
selectedTab(TAB_DASHBOARD);
break;
case R.id.action_chats:
selectedTab(TAB_CHATS);
break;
case R.id.action_settings:
selectedTab(TAB_SETTINGS);
break;
}
}
});
}
private void selectedTab(String tabId) {
mCurrentTab = tabId;
if(mStacks.get(tabId).size() == 0){
if(tabId.equals(TAB_PROFILE)){
Fragment fragment = new ProfileFragment();
Bundle args = new Bundle();
args.putSerializable("user", Globals.getCurrentUser());
fragment.setArguments(args);
pushFragments(tabId, fragment,true);
} else if(tabId.equals(TAB_DASHBOARD)){
pushFragments(tabId, new DashboardFragment(),true);
}else if(tabId.equals(TAB_CHATS)){
pushFragments(tabId, new GroupsFragment(),true);
}else if(tabId.equals(TAB_SETTINGS)){
pushFragments(tabId, new SettingsFragment(),true);
}
}else {
pushFragments(tabId, mStacks.get(tabId).lastElement(),false);
}
}
public void pushFragments(String tag, Fragment fragment, boolean shouldAdd){
if(shouldAdd)
mStacks.get(tag).push(fragment);
FragmentManager manager = getFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.content, fragment);
ft.commit();
}
public void popFragments(){
Fragment fragment = mStacks.get(mCurrentTab).elementAt(mStacks.get(mCurrentTab).size() - 2);
mStacks.get(mCurrentTab).pop();
FragmentManager manager = getFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.content, fragment);
ft.commit();
}
@Override
public void onBackPressed() {
if(mStacks.get(mCurrentTab).size() == 1){
finish();
return;
}
popFragments();
}
}

使用设置新片段

((MainActivity)context).pushFragments(MainActivity.TAB_CHATS, fragment,true);

布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:background="@color/background_material_light"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/bottom_navigation"/>
<android.support.design.widget.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
app:itemBackground="@color/waPrimary"
app:itemIconTint="@color/white"
app:itemTextColor="@color/white"
app:menu="@menu/menu_bottom_navigation" />

屏幕旋转时一切正常,但应用程序崩溃,应用程序隐藏时除外。

java.lang.RuntimeException:Parcel:无法封送值%FragageName%{c985244#2 id=0x7f090051}

正如我所读到的,当我试图传递的对象之一不是Parceable,但不知道如何修复时,就会发生这种情况。有什么想法吗?

UPD

在我制作了所有的碎片Serializable之后,新的异常抛出

java.lang.RuntimeException:Parcelable遇到IOException写入可序列化对象(name=%FrageName%)

引起原因:java.io.NotSerializableException:android.support.v7.widget.RecyclerView

UPD2

似乎找到了一个解决方案-transient属性。现在,我正试图使所有不可序列化的对象都是瞬态的。

UPD3

它起了作用,但我不知道它是否足够有效。

这是我的建议:

  1. 您的活动维护对底部导航切换所需的四个片段的引用
  2. 在切换底部导航时,替换活动片段管理器中的当前片段
  3. 在给定的片段上,当您与UI交互时,您内容推送到片段子片段管理器

这样,每个片段都会自动维护自己的后台,您不必保存任何状态,而且一切都很好™.

一些可能有帮助的示例代码。

public class MainActivity extends AppCompatActivity {
private Fragment mProfileFragment;
private Fragment mDashboardFragment;
private Fragment mChatsFragment;
private Fragment mSettingsFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
// Init fragments
}
else {
// Find last active fragments in fragment manager
}
setupViews();
}
private void setupViews() {
BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_navigation);
bottomNavigationView.setSelectedItemId(R.id.action_dashboard);
BottomNavigationViewHelper.removeShiftMode(bottomNavigationView);
bottomNavigationView.setOnNavigationItemSelectedListener(item -> {
Fragment fragment;
switch (item.getItemId()) {
case R.id.action_profile:
fragment = mProfileFragment;
break;
case R.id.action_dashboard:
fragment = mDashboardFragment;
break;
case R.id.action_chats:
fragment = mChatsFragment;
break;
case R.id.action_settings:
fragment = mSettingsFragment;
break;
}
// Replace the currently active fragment which will be
// managing its own backstack
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.frament_container, fragment)
.commit();
});
}
}

你的一个碎片会把东西推到自己的堆栈上,就像这样:

public class ProfileFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.id.fragment_layout, container, false);
Button button = view.findViewById(R.id.some_button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Fragment someFragmentToPush = new SomeFragmentToPush();
// Use the child fragment manager to keep UI
// local to this fragment instance, adding to backstack
// for automatic popping on pressing back
getChildFragmentManager().beginTransaction()
.add(R.id.fragment_layout, someFragmentToPush)
.addToBackStack(null)
.commit();
}
});
return view;
}
}

希望能有所帮助!

最新更新