android修改配置或切换系统语言后的问题

Android修改配置后,比如切换系统语言。activity会被销毁然后重建.

当碰到这种销毁重建后,fragment如果没有无参构造方法,则会报错
报错信息如下
androidx.fragment.app.Fragment$InstantiationException: Unable to instantiate fragment com.XxxFragment: could not find Fragment constructor

在Fragment中找到这个报错的出处,代码如下

/**
     * Create a new instance of a Fragment with the given class name.  This is
     * the same as calling its empty constructor, setting the {@link ClassLoader} on the
     * supplied arguments, then calling {@link #setArguments(Bundle)}.
     *
     * @param context The calling context being used to instantiate the fragment.
     * This is currently just used to get its ClassLoader.
     * @param fname The class name of the fragment to instantiate.
     * @param args Bundle of arguments to supply to the fragment, which it
     * can retrieve with {@link #getArguments()}.  May be null.
     * @return Returns a new fragment instance.
     * @throws InstantiationException If there is a failure in instantiating
     * the given fragment class.  This is a runtime exception; it is not
     * normally expected to happen.
     * @deprecated Use {@link FragmentManager#getFragmentFactory()} and
     * {@link FragmentFactory#instantiate(ClassLoader, String)}, manually calling
     * {@link #setArguments(Bundle)} on the returned Fragment.
     */
    @Deprecated
    @NonNull
    public static Fragment instantiate(@NonNull Context context, @NonNull String fname,
            @Nullable Bundle args) {
        try {
            Class<? extends Fragment> clazz = FragmentFactory.loadFragmentClass(
                    context.getClassLoader(), fname);
            //通过无参构造方法反射获得fragment的实例
            Fragment f = clazz.getConstructor().newInstance();
            //用frangment的setArguments()传参
            if (args != null) {
                args.setClassLoader(f.getClass().getClassLoader());
                f.setArguments(args);
            }
            return f;
        } catch (java.lang.InstantiationException e) {
            throw new InstantiationException("Unable to instantiate fragment " + fname
                    + ": make sure class name exists, is public, and has an"
                    + " empty constructor that is public", e);
        } catch (IllegalAccessException e) {
            throw new InstantiationException("Unable to instantiate fragment " + fname
                    + ": make sure class name exists, is public, and has an"
                    + " empty constructor that is public", e);
        } catch (NoSuchMethodException e) {
        	//在这里报的错误
            throw new InstantiationException("Unable to instantiate fragment " + fname
                    + ": could not find Fragment constructor", e);
        } catch (InvocationTargetException e) {
            throw new InstantiationException("Unable to instantiate fragment " + fname
                    + ": calling Fragment constructor caused an exception", e);
        }
    }

从代码中可以看出,如果创建fragment时需要给fragment传递参数,最好用fragment.setArguments()方法传递参数,不要通过构造方法传递。防止在activity重建时因为没有无参构造方法,而报错。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 如果要在代码中切换 Android 设备的语言并重启应用程序,可以使用以下代码: ``` // 获取系统配置对象 Configuration config = getResources().getConfiguration(); // 设置新的语言 config.locale = new Locale("en"); // 更新配置 getResources().updateConfiguration(config, getResources().getDisplayMetrics()); // 重启应用程序 Intent intent = new Intent(this, MainActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(intent); finish(); ``` 注意,需要自己实现MainActivity.class,更改"en"为需要切换语言 ### 回答2: Android切换语言重启的代码可以通过修改系统配置并重新启动Activity来实现。具体步骤如下: 1. 首先,需要创建一个共享参数(SharedPreferences)来保存所选的语言设置。在Activity中定义一个SharedPreferences对象,用于存储和读取语言设置。例如: ``` SharedPreferences preferences = getSharedPreferences("LanguagePrefs", MODE_PRIVATE); ``` 2. 在需要切换语言的地方,首先获取到用户所选择的新语言。假设语言选择是通过点击按钮来实现的,使用一个String变量`newLanguage`保存新语言的值。例如: ``` String newLanguage = "en"; // 假设新使用英文(en)作为语言 ``` 3. 在切换语言之前,将新语言的值保存到共享参数中,以便在重启Activity后继续使用。使用SharedPreferences编辑器(Editor)添加或修改语言设置。例如: ``` SharedPreferences.Editor editor = preferences.edit(); editor.putString("language", newLanguage); editor.apply(); ``` 4. 重新启动Activity。通过调用当前Activity的`recreate()`方法,强制重启当前Activity,以便应用切换到新的语言。例如: ``` recreate(); ``` 5. 在Activity的`onCreate()`方法中,读取保存的语言设置并应用到应用程序的配置中。通过读取共享参数中保存的语言设置,然后调用`ContextWrapper`类的`attachBaseContext()`方法传入新的配置。例如: ``` @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 读取共享参数中保存的语言设置 String language = preferences.getString("language", ""); // 根据新语言设置重新配置应用 Context context = ChangeLanguageActivity.this; LocaleUtils.setLocale(context, language); // 自定义工具类设置应用语言 // ... } ``` 6. 最后,重新定义一个自定义工具类`LocaleUtils`,用于应用程序级别的语言设置。例如: ``` public class LocaleUtils { public static void setLocale(Context context, String language) { Locale locale = new Locale(language); Locale.setDefault(locale); Resources resources = context.getResources(); Configuration configuration = resources.getConfiguration(); configuration.setLocale(locale); configuration.setLayoutDirection(locale); resources.updateConfiguration(configuration, resources.getDisplayMetrics()); } } ``` 通过以上步骤,当用户切换语言后,会重新启动当前Activity并应用新语言配置。请注意,重启Activity可能会造成界面闪烁,所以可以添加一些过渡动画来提升用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值