这实际上是源自其他地方的问题,但我已将其缩小到以下情况。在我的MainActivity中,我使用ViewPager在底部有三个选项卡来交换我的三个片段。如果我在移动到任何片段后单击按钮移动到新活动,我会收到以下错误:
FATAL EXCEPTION: main
java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 861520 bytes
at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3752)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Caused by: android.os.TransactionTooLargeException: data parcel size 861520 bytes
at android.os.BinderProxy.transactNative(Native Method)
at android.os.BinderProxy.transact(Binder.java:615)
at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:3606)
at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3744)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
但是,如果我在ViewPager中的不同片段之间移动之前单击按钮,我就不会崩溃。我已经探索了使我的片段完全空的所有可能性,看看问题是否存在,但它似乎链接到MainActivity或FragmentStatePagerAdapater。
以下是他们的代码:
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import com.mypackage.Fragments.GroupsFragment;
import com.mypackage.Fragments.HomeFragment;
import com.mypackage.Fragments.ProfileFragment;
import com.mypackage.R;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Get the ViewPager and set it's PagerAdapter so that it can display items
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
viewPager.setAdapter(new MainFragmentPagerAdapter(getSupportFragmentManager()));
// Give the TabLayout the ViewPager
TabLayout tabLayout = (TabLayout) findViewById(R.id.sliding_tabs);
tabLayout.setupWithViewPager(viewPager);
Button mTestButton = (Button) findViewById(R.id.test);
mTestButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
moveToGroupActivity();
}
});
}
public void moveToGroupActivity() {
Intent myIntent = new Intent(this, GroupActivity.class);
startActivity(myIntent);
}
public static class MainFragmentPagerAdapter extends FragmentStatePagerAdapter {
final int PAGE_COUNT = 3;
private String tabTitles[] = new String[] { "Home", "Groups", "Profile" };
public MainFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public int getCount() {
return PAGE_COUNT;
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return HomeFragment.newInstance();
case 1:
return GroupsFragment.newInstance();
case 2:
return ProfileFragment.newInstance();
default:
return null;
}
}
@Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tabTitles[position];
}
}
}
要清楚:我有一个按钮移动到Activity中的不同Activity,该Activity包含一个在三个片段之间移动的ViewPager。如果我在移动到另一个片段之前单击该按钮,它将加载正常。如果我移动到片段然后单击按钮,我会看到上面提到的崩溃。
我从不使用onSaveInstanceState()或类似的东西。我唯一的猜测是FragmentStatePagerAdapter将片段放入内存并导致崩溃,但我真的不知道。
答案 0 :(得分:0)
TransactionTooLargeException已经困扰我们大约4个月了,我们终于解决了该问题!
发生的事情是我们在ViewPager中使用了FragmentStatePagerAdapter。用户将翻阅并创建100多个片段(其阅读应用程序)。
尽管我们在destroyItem()中正确管理了片段,但是在Android的FragmentStatePagerAdapter实现中,存在一个错误,该错误保留对以下列表的引用:
private ArrayList<Fragment.SavedState> mSavedState = new ArrayList<Fragment.SavedState>();
当Android的FragmentStatePagerAdapter尝试保存状态时,它将调用该函数
@Override
public Parcelable saveState() {
Bundle state = null;
if (mSavedState.size() > 0) {
state = new Bundle();
Fragment.SavedState[] fss = new Fragment.SavedState[mSavedState.size()];
mSavedState.toArray(fss);
state.putParcelableArray("states", fss);
}
for (int i=0; i<mFragments.size(); i++) {
Fragment f = mFragments.get(i);
if (f != null && f.isAdded()) {
if (state == null) {
state = new Bundle();
}
String key = "f" + i;
mFragmentManager.putFragment(state, key, f);
}
}
return state;
}
如您所见,即使您适当地管理FragmentStatePagerAdapter子类中的片段,基类仍将为曾经创建的每个片段存储Fragment.SavedState。当该数组转储到parcelableArray并且操作系统不希望它超过100个项目时,将发生TransactionTooLargeException。
因此,对我们而言,解决方法是重写saveState()方法,而不为“状态”存储任何内容。
@Override
public Parcelable saveState() {
Bundle bundle = (Bundle) super.saveState();
bundle.putParcelableArray("states", null); // Never maintain any states from the base class, just null it out
return bundle;
}
答案 1 :(得分:0)
清除最后保存的对象实例可以解决此问题。尝试在您的活动课中使用。
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.clear();
}