设置 Activity 在 android 10 中启动时崩溃在 android 28< 中运行良好。如何解决?

Setting Activity crashing while launching in android 10 works well in android 28<. How to fix it?

我有一个包含设置的 activity。启动 SettingsActivity.java 后崩溃。它在物理设备上测试时效果很好,即 API 19、API23、API26。我只在 API 29 遇到过这个问题。 此问题的原因是什么以及如何解决?参考下面的代码

SettingActivity.java

package ak.wp.meto.activity;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.view.MenuItem;
import android.widget.Toast;
import java.io.File;

public class SettingsActivity extends AppCompatActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        initView();
        initToolbar();
    }

    private void initView() {
        setContentView(R.layout.activity_settings);

        // replace linear layout by preference screen
        getFragmentManager().beginTransaction().replace(R.id.content, new MyPreferenceFragment()).commit();
    }

    private void initToolbar() {
        Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(mToolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setDisplayShowHomeEnabled(true);
        getSupportActionBar().setTitle(getString(R.string.settings));

    }

    @SuppressLint("ValidFragment")
    public class MyPreferenceFragment extends PreferenceFragment {
        @Override
        public void onCreate(final Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.xml.settings_preference);
            // clears web cache
            final CheckBoxPreference clr_webcache = (CheckBoxPreference) getPreferenceManager().findPreference("perf_cache_clr");
            clr_webcache.setChecked(false);
            clr_webcache.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {

                @Override
                public boolean onPreferenceChange(Preference preference, Object newValue) {
                    Toast.makeText(getApplicationContext(),"Clearing Cache, Please Wait",Toast.LENGTH_SHORT).show();
                    try {
                        trimCache(getActivity());
                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    return true;
                }
            });
        }

        private void trimCache(Context context) {

            try {
                File dir = context.getCacheDir();
                if (dir != null && dir.isDirectory()) {
                    deleteDir(dir);
                }
            } catch (Exception e) {
                // TODO: handle exception
            }

        }

        private boolean deleteDir(File dir) {

            if (dir != null && dir.isDirectory()) {
                String[] children = dir.list();
                for (int i = 0; i < children.length; i++) {
                    boolean success = deleteDir(new File(dir, children[i]));
                    if (!success) {
                        Toast.makeText(getApplicationContext(),"FAILED:Try clearing using device settings",Toast.LENGTH_SHORT).show();
                        return false;
                    }else{
                        Toast.makeText(getApplicationContext(),"SUCCESS: CACHE CLEARED",Toast.LENGTH_SHORT).show();
                    }
                }
            }
            // The directory is now empty so delete it
            return dir.delete();
        }
        //END OF MYPREFERENCE FRAGMENT
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                finish();
                return true;

            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public void onBackPressed() {
        finish();
    }
}

这是我的activity_settings.xml

activity_settings.xml

<?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:layout_width="match_parent"
    android:layout_height="match_parent">

    <include
        android:id="@+id/toolbarTop"
        layout="@layout/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <LinearLayout
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/toolbarTop"
        android:orientation="horizontal" />

</RelativeLayout>

这是我的setting_preference.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

    <CheckBoxPreference
        android:key="perf_notification"
        android:title="@string/pref_notification_title"
        android:summary="@string/pref_notification_summ"
        android:defaultValue="true" />


    <ListPreference
        android:key="pref_font_size"
        android:title="@string/pref_text_title"
        android:dialogTitle="@string/select_size"
        android:entries="@array/text_entries"
        android:entryValues="@array/text_entries"
        android:defaultValue="@string/default_text" />


    <CheckBoxPreference
        android:key="perf_cache_clr"
        android:title="Clear Cache"
        android:summary="Deletes Cache to Load Latest Updates "
        android:defaultValue="false" />

</PreferenceScreen>

Logcat 在第 28 和 36 行的 SettingsActivity.java 中表示致命异常 LOGCAT

2020-10-23 11:24:23.025 19845-19845/? E/AndroidRuntime: FATAL EXCEPTION: main
    Process: ak.wp.meto, PID: 19845
    java.lang.RuntimeException: Unable to start activity ComponentInfo{ak.wp.meto/ak.wp.meto.activity.SettingsActivity}: java.lang.IllegalStateException: Fragment ak.wp.meto.activity.SettingsActivity.MyPreferenceFragment must be a public static class to be  properly recreated from instance state.
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3632)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3784)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2270)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:237)
        at android.app.ActivityThread.main(ActivityThread.java:8125)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)
     Caused by: java.lang.IllegalStateException: Fragment ak.wp.meto.activity.SettingsActivity.MyPreferenceFragment must be a public static class to be  properly recreated from instance state.
        at android.app.BackStackRecord.doAddOp(BackStackRecord.java:429)
        at android.app.BackStackRecord.replace(BackStackRecord.java:470)
        at android.app.BackStackRecord.replace(BackStackRecord.java:462)
        at ak.wp.meto.activity.SettingsActivity.initView(SettingsActivity.java:36)
        at ak.wp.meto.activity.SettingsActivity.onCreate(SettingsActivity.java:28)
        at android.app.Activity.performCreate(Activity.java:7957)
        at android.app.Activity.performCreate(Activity.java:7946)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3607)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3784) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2270) 
        at android.os.Handler.dispatchMessage(Handler.java:107) 
        at android.os.Looper.loop(Looper.java:237) 
        at android.app.ActivityThread.main(ActivityThread.java:8125) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)

我在第 36 行遇到错误

getFragmentManager().beginTransaction().replace(R.id.content, new MyPreferenceFragment()).commit();

依次为函数 initView() 第 28 行

给出了 ERROR

请帮我解决这个问题

您必须创建 SettingsFragment 的实例才能启动它

public static MyPreferenceFragment getInstance() {
    MyPreferenceFragment fragment = new MyPreferenceFragment();
    Bundle bundle = new Bundle();
    fragment.setArguments(bundle);
    return fragment;
}

并通过调用

替换它
getFragmentManager().beginTransaction().replace(R.id.content, MyPreferenceFragment.getInstance()).commit();

将 Fragment 放入一个单独的文件中,该文件的名称与 Fragment (MyPreferenceFragment.java) 的名称相同。它应该可以解决问题。

同时检查新的 Preference 库。 Android.preference 正在弃用。而不是:

import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceFragment;

使用:

import androidx.fragment.app.Fragment
import androidx.preference.CheckBoxPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat

BINGO,我解决了!!! 最后,这对我有用: 我将 MyPreferenceFragment 设为 static class

public static class MyPreferenceFragment extends PreferenceFragment 

第二个问题是 Toast.makeText 发出错误消息说要使 MyPreferenceFragment 不是静态的。所以我用

替换了 Toast
Toast.makeText(getActivity().getApplicationContext(),"Clearing Cache, Please Wait",Toast.LENGTH_SHORT).show();

谢谢大家的支持。