我得到了一个TransactionTooLargeException。无法复制的。文件里说

The Binder transaction failed because it was too large. During a remote procedure call, the arguments and the return value of the call are transferred as Parcel objects stored in the Binder transaction buffer. If the arguments or the return value are too large to fit in the transaction buffer, then the call will fail and TransactionTooLargeException will be thrown. ... There are two possible outcomes when a remote procedure call throws TransactionTooLargeException. Either the client was unable to send its request to the service (most likely if the arguments were too large to fit in the transaction buffer), or the service was unable to send its response back to the client (most likely if the return value was too large to fit in the transaction buffer). ...

在某个地方,我传递或接收的参数超出了未知的限制。在哪里?

stacktrace没有显示任何有用的东西:

java.lang.RuntimeException: Adding window failed
at android.view.ViewRootImpl.setView(ViewRootImpl.java:548)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:406)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:320)
at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:152)
at android.view.Window$LocalWindowManager.addView(Window.java:557)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2897)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
at android.app.ActivityThread.access$600(ActivityThread.java:139)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1262)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:4977)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.os.TransactionTooLargeException
at android.os.BinderProxy.transact(Native Method)
at android.view.IWindowSession$Stub$Proxy.add(IWindowSession.java:569)
at android.view.ViewRootImpl.setView(ViewRootImpl.java:538)
... 16 more
android.os.TransactionTooLargeException
at android.os.BinderProxy.transact(Native Method)
at android.view.IWindowSession$Stub$Proxy.add(IWindowSession.java:569)
at android.view.ViewRootImpl.setView(ViewRootImpl.java:538)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:406)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:320)
at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:152)
at android.view.Window$LocalWindowManager.addView(Window.java:557)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2897)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
at android.app.ActivityThread.access$600(ActivityThread.java:139)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1262)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:4977)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)

这似乎和观点有关?这与远程过程调用有什么关系?

可能重要的是:Android版本:4.0.3,设备:HTC One X


当前回答

确保你没有在Intent对象中放入大容量的数据。在我的情况下,我添加字符串500k大小,然后开始另一个活动。除了这个例外,它总是失败。我通过使用活动的静态变量避免了在活动之间共享数据——你不需要将它们发送到Intent,然后从Intent中提取。

我有的:

String html = new String();//some string of 500K data.
Intent intent = new Intent(MainActivity.this, PageWebView.class);
//this is workaround - I just set static variable and then access it from another    activity.
MainActivity.htmlBody = timelineDb.getHTMLBodyForTweet(tweet);
//This line was present and it actually failed with the same exception you had.
//intent.putExtra("com.gladimdim.offtie.webview", html);

其他回答

对我来说,TransactionTooLargeException发生时,我试图发送大位图图像从一个活动到另一个通过意图。我通过使用应用程序的全局变量解决了这个问题。

例如,如果你想从活动A发送一个大的位图图像到活动B,那么将这个位图图像存储在全局变量中

((Global) this.getApplication()).setBitmap(bitmap);

然后启动活动B并从全局变量中读取

Bitmap bitmap = ((Global) this.getApplication()).getBitmap();

问题通过以下方式解决:

 Bundle bundle = new Bundle();
  bundle.putSerializable("data", bigdata);
...
  CacheHelper.saveState(bundle,"DATA");
  Intent intent = new Intent(mActivity, AActivity.class);
  startActivity(intent, bb);// do not put data to intent.

In Activity:
   @Override
   protected void onCreate(Bundle savedInstanceState) {
        Bundle bundle = CacheHelper.getInstance().loadState(Constants.DATA);
        if (bundle != null){
            Intent intent = getIntent();
            intent.putExtras(bundle);
        }
        getIntent().getExtra(..);
        ....
   }
   @Override
    protected void onDestroy() {
        super.onDestroy();
        CacheHelper.clearState("DATA");
    }

public class CacheHelper {

    public static void saveState(Bundle savedInstanceState, String name) {
        Bundle saved = (Bundle) savedInstanceState.clone();
        save(name, saved);
    }
    public Bundle loadState(String name) {

        Object object = load(name);
        if (object != null) {
            Bundle bundle = (Bundle) object;
            return bundle;
        }
        return null;
    }
    private static void save(String fileName, Bundle object) {
        try {
            String path = StorageUtils.getFullPath(fileName);
            File file = new File(path);
            if (file.exists()) {
                file.delete();
            }
            FileOutputStream fos = new FileOutputStream(path, false);

            Parcel p = Parcel.obtain(); //creating empty parcel object
            object.writeToParcel(p, 0); //saving bundle as parcel
            //parcel.writeBundle(bundle);
            fos.write(p.marshall()); //writing parcel to file

            fos.flush();
            fos.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private static Bundle load(String fileName) {
        try {
            String path = StorageUtils.getFullPath(fileName);
            FileInputStream fis = new FileInputStream(path);

            byte[] array = new byte[(int) fis.getChannel().size()];
            fis.read(array, 0, array.length);

            Parcel parcel = Parcel.obtain(); //creating empty parcel object
            parcel.unmarshall(array, 0, array.length);
            parcel.setDataPosition(0);
            Bundle out = parcel.readBundle();
            out.putAll(out);

            fis.close();
            parcel.recycle();
            return out;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
public static void clearState(Activity ac) {
    String name = ac.getClass().getName();
    String path = StorageUtils.getFullPath(name);
    File file = new File(path);
    if (file.exists()) {
        file.delete();
    }
}
}

对我来说,它也是FragmentStatePagerAdapter,然而覆盖saveState()不起作用。以下是我的解决方法:

当调用FragmentStatePagerAdapter构造函数时,在类中保持一个单独的片段列表,并添加一个方法来删除这些片段:

class PagerAdapter extends FragmentStatePagerAdapter {
    ArrayList<Fragment> items;

    PagerAdapter(ArrayList<Fragment> frags) {
        super(getFragmentManager()); //or getChildFragmentManager() or getSupportFragmentManager()
        this.items = new ArrayList<>();
        this.items.addAll(frags);
    }

    public void removeFragments() {
        Iterator<Fragment> iter = items.iterator();

        while (iter.hasNext()) {
            Fragment item = iter.next();
                getFragmentManager().beginTransaction().remove(item).commit();
                iter.remove();
            }
            notifyDataSetChanged();
        }
    }
    //...getItem() and etc methods...
}

然后在Activity中,保存ViewPager的位置,并在重写的onSaveInstanceState()方法中调用adapter.removeFragments():

private int pagerPosition;

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    //save other view state here
    pagerPosition = mViewPager.getCurrentItem();
    adapter.removeFragments();
}

最后,在重写的onResume()方法中,如果适配器不为空,则重新实例化它。(如果它是空的,那么Activity是第一次被打开或应用程序被Android杀死后,onCreate将做适配器创建。)

@Override
public void onResume() {
    super.onResume();
    if (adapter != null) {
        adapter = new PagerAdapter(frags);
        mViewPager.setAdapter(adapter);
        mViewPager.setCurrentItem(currentTabPosition);
    }
}

作为意图,内容提供者,信使,所有系统服务,如电话,振动器等都使用Binder提供的IPC基础设施。此外,活动生命周期回调也使用这个基础结构。

1MB是系统在特定时刻执行的所有绑定器事务的总限制。

如果在发送意图时有很多事务发生,即使额外的数据并不大,它也可能会失败。http://codetheory.in/an-overview-of-android-binder-framework/

你已经从onSaveInstanceState方法中清除了旧的InstanceState,它会工作得很好。我使用FragmentStatePagerAdapter为我的viewpager,所以我保持下面覆盖方法到我的父活动为清晰的InstanceState。

@Override
protected void onSaveInstanceState(Bundle InstanceState) {
             super.onSaveInstanceState(InstanceState);
             InstanceState.clear();
}

我发现这个解决方案从这里android.os.TransactionTooLargeException在牛轧糖