AndroidX: 在Android 10设备上遇到只能写入可序列化对象的IOException

8 浏览
0 Comments

AndroidX: 在Android 10设备上遇到只能写入可序列化对象的IOException

在Android 10设备中,我遇到了Parcelable遇到IOException写序列化对象的问题,原因是java.io.NotSerializableException: androidx.appcompat.widget.Toolbar错误。\n我搜索了很多解决方案,但每个解决方案都告诉我在内部类和子内部类中定义implement serializable,我也已经这样做了,但仍然只在Android 10设备上出现这个错误。\n如果我使用transient关键字定义View或对象,那么这个错误将会被修复,但是另一个View、适配器和类也会出现相同的错误。\nLogcat\n

java.lang.RuntimeException: Parcelable遇到IOException写序列化对象(名称= com.android.ui.fragment.CustomViewFragment)
        at android.os.Parcel.writeSerializable(Parcel.java:1850)
        at android.os.Parcel.writeValue(Parcel.java:1797)
        at android.os.Parcel.writeArrayMapInternal(Parcel.java:945)
        at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1584)
        at android.os.Bundle.writeToParcel(Bundle.java:1253)
        at android.os.Parcel.writeBundle(Parcel.java:1014)
        at android.content.Intent.writeToParcel(Intent.java:11155)
        at android.app.IActivityTaskManager$Stub$Proxy.startAppLockService(IActivityTaskManager.java:8468)
        at android.app.Activity.startAppLockService(Activity.java:8950)
        at android.app.Activity.performStart(Activity.java:8022)
        at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3512)
        at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221)
        at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201)
        at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2175)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:237)
        at android.app.ActivityThread.main(ActivityThread.java:7860)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1075)
     Caused by: java.io.NotSerializableException: androidx.appcompat.widget.Toolbar
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1240)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1604)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1565)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1488)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1234)
        at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1604)
        at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1565)
        at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1488)
        at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1234)
        at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:354)
        at android.os.Parcel.writeSerializable(Parcel.java:1845)
        at android.os.Parcel.writeValue(Parcel.java:1797) 
        at android.os.Parcel.writeArrayMapInternal(Parcel.java:945) 
        at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1584) 
        at android.os.Bundle.writeToParcel(Bundle.java:1253) 
        at android.os.Parcel.writeBundle(Parcel.java:1014) 
        at android.content.Intent.writeToParcel(Intent.java:11155) 
        at android.app.IActivityTaskManager$Stub$Proxy.startAppLockService(IActivityTaskManager.java:8468) 
        at android.app.Activity.startAppLockService(Activity.java:8950) 
        at android.app.Activity.performStart(Activity.java:8022) 
        at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3512) 
        at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221) 
        at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201) 
        at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2175) 
        at android.os.Handler.dispatchMessage(Handler.java:107) 
        at android.os.Looper.loop(Looper.java:237) 
        at android.app.ActivityThread.main(ActivityThread.java:7860) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1075) 

\nActivity.java\n

   public class BaseFragmentActivity extends AppCompatActivity implements Serializable, View.OnClickListener {
        private static final String TAG = "BaseFragmentActivity";
        private Toolbar mToolbar;
        private ImageView tBtnSave, tBtnBack;
        private TextView tTxtTitle;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_base_fragment);
            mToolbar = findViewById(R.id.toolbar);
            tBtnSave = findViewById(R.id.toolbar_btn_save);
            tBtnBack = findViewById(R.id.toolbarBtnBack);
            tTxtTitle = findViewById(R.id.toolbar_title);
        }
        ...
}

\nbuild.gradle\n

apply plugin: 'com.android.application'
android {
    compileSdkVersion 29
    defaultConfig {
        applicationId "com.android.app"
        minSdkVersion 21
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        vectorDrawables.useSupportLibrary = true
        multiDexEnabled true
    }
    buildTypes {
        debug {
            debuggable true
            buildConfigField "Boolean", "DEBUG_MODE", "true"
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:support-annotations:28.0.0'
    annotationProcessor 'com.android.support:support-annotations:28.0.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'com.google.android.material:material:1.1.0'
    implementation 'com.google.code.gson:gson:2.8.5'
    implementation 'com.github.bumptech.glide:glide:4.11.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
    implementation 'com.android.volley:volley:1.1.1'
    implementation 'androidx.palette:palette:1.0.0'
    //External Animation Library
    implementation 'com.airbnb.android:lottie:3.4.1'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}

\n编辑并修复。\n

public class BaseFragmentActivity extends AppCompatActivity implements Serializable, View.OnClickListener {
        // 通过使用`transient`关键字来定义View或类来表示它们不是被序列化的视图或类。
        private static final String TAG = "BaseFragmentActivity";
        private transient Toolbar mToolbar;
        private transient AppCompatImageView tBtnSave, tBtnBack;
        private transient AppCompatTextView tTxtTitle;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_base_fragment);
            mToolbar = findViewById(R.id.toolbar);
            tBtnSave = findViewById(R.id.toolbar_btn_save);
            tBtnBack = findViewById(R.id.toolbarBtnBack);
            tTxtTitle = findViewById(R.id.toolbar_title);
        }
        ...
}

0
0 Comments

AndroidX : Parcelable遇到了在Android 10设备上写入可序列化对象时遇到IOException的问题。

问题原因:

在Android 10设备上,当使用AndroidX的Parcelable接口进行序列化时,遇到了IOException异常。这是因为在Android 10版本中,对于Parcelable接口的序列化,会涉及到底层的存储和读取操作,而在某些情况下,可能会遇到文件写入错误的问题。

解决方法:

解决AndroidX : Parcelable遇到IOException的问题,可以尝试以下解决方法:

1. 检查对象中的成员变量是否正确实现了Parcelable接口。确保所有成员变量都正确地实现了Parcelable接口,并且在写入和读取过程中没有出现问题。

2. 检查是否有非序列化的成员变量。在对象中,如果存在某些成员变量不需要被序列化保存,可以使用transient关键字进行修饰。transient关键字可以告诉编译器该变量不是可序列化方法的一部分。

以下是一个示例代码,演示了如何在AndroidX中正确使用Parcelable接口,并使用transient关键字标记非序列化的成员变量:

import android.os.Parcel;
import android.os.Parcelable;
public class ExampleParcelable implements Parcelable {
    private String name;
    private int age;
    private transient String password; // 非序列化成员变量
    public ExampleParcelable(String name, int age, String password) {
        this.name = name;
        this.age = age;
        this.password = password;
    }
    protected ExampleParcelable(Parcel in) {
        name = in.readString();
        age = in.readInt();
        // 读取时需要手动处理非序列化成员变量
        // password = in.readString();
    }
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeInt(age);
        // 写入时不需要将非序列化成员变量写入
        // dest.writeString(password);
    }
    @Override
    public int describeContents() {
        return 0;
    }
    public static final Creator CREATOR = new Creator() {
        @Override
        public ExampleParcelable createFromParcel(Parcel in) {
            return new ExampleParcelable(in);
        }
        @Override
        public ExampleParcelable[] newArray(int size) {
            return new ExampleParcelable[size];
        }
    };
}

通过以上解决方法,我们可以避免AndroidX : Parcelable在Android 10设备上遇到IOException的问题,确保对象的正确序列化和反序列化操作。

0
0 Comments

在你的代码中的某个地方,你试图将一个完整的Fragment(看起来是CustomViewFragment)写入到parcel中。出现这个错误的原因是Fragment的上下文是Activity(可能是BaseFragmentActivity的子类),它也会经历序列化的过程。但是Fragment和Activity都没有实现Serializable接口,所以需要让类及其所有成员实现Serializable接口。

你说得对,我必须让“可序列化的类及其所有成员实现Serializable”所以我使用了transient关键字来定义所有必需的视图、对象和类。谢谢你的帮助,我永远不会忘记你。

只是一点小建议:不要序列化Activities和Fragments(以及与android.content.Context相关的任何内容)。

但是,如果我通过bundle从activity传递对象到fragment的putSerializable(key,object)中,我应该怎么做呢?在这种情况下,我们需要确保我们的fragment是可序列化的。你能解释一下为什么我们不应该在fragments和activities中实现Serializable吗?

Activity负责UI、资源和业务逻辑之间的连接。"一个Activity提供了绘制UI的窗口" - source。Fragment的创建是为了帮助减小Activity的大小。

当你在fragment或activity之间传递数据时,你只传递纯粹的数据。例如,你只传递用户ID而不是整个用户配置文件,使用bundle。在接收端,你提取ID并加载用户配置文件。当你传递大量数据时,你可能会遇到TransactionTooLargeException - 当传递的数据量超过±1Mb时。

简而言之:只传递需要的数据。你不需要一个完整的fragment,你只需要它所包含的东西。

对于每个开发者来说,这似乎是有用的。感谢你花时间帮助我。

0