1. ホーム
  2. android

Nougatでのandroid.os.TransactionTooLargeExceptionについて

2023-10-05 22:18:27

質問

Nexus 5X を Android N にアップデートしたのですが、アプリ (デバッグまたはリリース) をインストールすると、エクストラで Bundle があるすべての画面遷移で TransactionTooLargeException が発生しました。他のデバイスではアプリが動作しています。PlayStoreにあるほとんど同じコードの古いアプリは、Nexus 5Xで動作しています。 同じ問題を抱えている人はいますか?

java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 592196 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 592196 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) 

どのように解決するのですか?

結局、私の問題はonSaveInstanceで保存されるもので、次のアクティビティに送信されるものではなかったのです。オブジェクトのサイズを制御できない場所 (ネットワーク応答) の保存をすべて削除したら、うまくいくようになりました。

アップデート 2。

GoogleはAndroidX ViewModelを提供しています。これはretainされたFragmentと同じ技術に基づいていますが、より簡単に使用することができます。現在では、ViewModel が好ましいアプローチとなっています。

アップデート 1:

大きなデータの塊を保存するために、Googleはインスタンスを保持するFragmentでそれを行うことを提案しています。アイデアとしては、バンドルに保存されるような必要なフィールドをすべて含むビューのない空のフラグメントを作成することです。追加 setRetainInstance(true); をFragmentのonCreateメソッドに追加します。 そして、ActivityのonDestroyでFragmentにデータを保存し、onCreateでそれを読み込む。 以下はActivityの例です。

public class MyActivity extends Activity {

    private DataFragment dataFragment;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // find the retained fragment on activity restarts
        FragmentManager fm = getFragmentManager();
        dataFragment = (DataFragment) fm.findFragmentByTag(“data”);

        // create the fragment and data the first time
        if (dataFragment == null) {
            // add the fragment
            dataFragment = new DataFragment();
            fm.beginTransaction().add(dataFragment, “data”).commit();
            // load the data from the web
            dataFragment.setData(loadMyData());
        }

        // the data is available in dataFragment.getData()
        ...
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // store the data in the fragment
        dataFragment.setData(collectMyLoadedData());
    }
}

Fragmentの例です。

public class DataFragment extends Fragment {

    // data object we want to retain
    private MyDataObject data;

    // this method is only called once for this fragment
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // retain this fragment
        setRetainInstance(true);
    }

    public void setData(MyDataObject data) {
        this.data = data;
    }

    public MyDataObject getData() {
        return data;
    }
}

詳しくは、以下の記事をご覧ください。 をご覧ください。 .