2024年最全Android 多语言应用(步骤+源码),面试题目100及最佳答案

最后的最后

对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!

当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的

最后,互联网不存在所谓的寒冬,只是你没有努力罢了!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

Slovak, Slovakia (sk_SK) ------------------------------斯洛伐克语,斯洛伐克

Slovenian, Slovenia (sl_SI) ---------------------------斯洛文尼亚语,斯洛文尼亚

Serbian (sr_RS) ----------------------------------------塞尔维亚语

Swedish, Sweden (sv_SE) ----------------------------瑞典语,瑞典

Thai, Thailand (th_TH) --------------------------------泰语,泰国

Tagalog, Philippines (tl_PH) --------------------------菲律宾语,菲律宾

Turkish, Turkey (tr_TR) -------------------------------土耳其语,土耳其

Ukrainian, Ukraine (uk_UA) --------------------------联合王国

Vietnamese, Vietnam (vi_VN) -----------------------越南语,越南

Chinese, PRC (zh_CN)--------------------------------中文,中国

Chinese, Taiwan (zh_rTW)-----------------------------中文,台湾

values-加上后面括号里面的值就可以了。不保证一定正确,不正确的可以参考刚才AS手动添加语言文件夹步骤。

这里只是一个简单的教程而已,所以我会把刚才新建的values-zh删掉,因为已经有默认的values表示中文了。

多语言因为要注意一个点,当你添加了一个文字资源时,对应的语言文件夹里都要添加,比如我在values的strings.xml中添加了一个你好,那么就要在values-en的strings.xml中添加一个Hello,同样也要在values-zh-rTW下的strings.xml中添加你好。你好的简体和繁体都是一样的。

四、修改页面适配Android系统语言


下面修改一下activity_main.xml的布局

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”

xmlns:app=“http://schemas.android.com/apk/res-auto”

xmlns:tools=“http://schemas.android.com/tools”

android:layout_width=“match_parent”

android:layout_height=“match_parent”

android:fitsSystemWindows=“true”

android:orientation=“vertical”

tools:context=“.MainActivity”>

<androidx.appcompat.widget.Toolbar

android:id=“@+id/toolbar”

android:layout_width=“match_parent”

android:layout_height=“?attr/actionBarSize”

android:background=“?attr/colorPrimary”>

<TextView

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_gravity=“center”

android:text=“@string/multi_language”

android:textColor=“#000”

android:textSize=“18sp” />

<ImageView

android:id=“@+id/iv_setting”

android:layout_width=“24dp”

android:layout_height=“24dp”

android:layout_gravity=“end”

android:layout_marginRight=“12dp”

android:src=“@drawable/ic_settings” />

</androidx.appcompat.widget.Toolbar>

<LinearLayout

android:layout_width=“match_parent”

android:layout_height=“match_parent”

android:gravity=“center”

android:orientation=“vertical”>

<TextView

android:id=“@+id/tv_sys_language”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:text=“@string/system_language”

android:textColor=“#000”

android:textSize=“16sp” />

<TextView

android:id=“@+id/tv_cur_language”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_marginTop=“12dp”

android:text=“@string/current_language”

android:textColor=“#000”

android:textSize=“16sp” />

<TextView

android:id=“@+id/tv_other_pages”

android:layout_width=“match_parent”

android:layout_height=“?attr/actionBarSize”

android:layout_marginTop=“50dp”

android:background=“#FFF”

android:gravity=“center”

android:text=“@string/other_pages”

android:textColor=“#000”

android:textSize=“16sp” />

然后修改activity_other.xml的布局

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”

xmlns:app=“http://schemas.android.com/apk/res-auto”

xmlns:tools=“http://schemas.android.com/tools”

android:layout_width=“match_parent”

android:layout_height=“match_parent”

android:fitsSystemWindows=“true”

tools:context=“.OtherActivity”>

<androidx.appcompat.widget.Toolbar

android:id=“@+id/toolbar”

app:navigationIcon=“@drawable/ic_return”

android:layout_width=“match_parent”

android:layout_height=“?attr/actionBarSize”

android:background=“?attr/colorPrimary”>

<TextView

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_gravity=“center”

android:text=“@string/other_pages”

android:textColor=“#000”

android:textSize=“18sp” />

</androidx.appcompat.widget.Toolbar>

最后修改activity_setting.xml的布局

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”

xmlns:app=“http://schemas.android.com/apk/res-auto”

xmlns:tools=“http://schemas.android.com/tools”

android:layout_width=“match_parent”

android:layout_height=“match_parent”

android:orientation=“vertical”

android:fitsSystemWindows=“true”

tools:context=“.SettingActivity”>

<androidx.appcompat.widget.Toolbar

android:id=“@+id/toolbar”

android:layout_width=“match_parent”

app:navigationIcon=“@drawable/ic_return”

android:layout_height=“?attr/actionBarSize”

android:background=“?attr/colorPrimary”>

<TextView

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_gravity=“center”

android:text=“@string/setting”

android:textColor=“#000”

android:textSize=“18sp” />

</androidx.appcompat.widget.Toolbar>

<LinearLayout

android:orientation=“vertical”

android:layout_width=“match_parent”

android:layout_height=“match_parent”>

<TextView

android:id=“@+id/tv_choose_lang”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_marginBottom=“8dp”

android:layout_marginStart=“16dp”

android:layout_marginTop=“24dp”

android:text=“@string/choose_lang”

android:textColor=“#7A7A7A”

android:textSize=“12sp” />

<RelativeLayout

android:id=“@+id/lay_system”

android:layout_width=“match_parent”

android:layout_height=“44dp”

android:background=“#FFF”

android:gravity=“center_vertical”>

<TextView

android:layout_width=“wrap_content”

android:layout_height=“match_parent”

android:layout_marginStart=“16dp”

android:gravity=“center”

android:text=“@string/system_lang”

android:textColor=“#4A4A4A”

android:textSize=“14sp” />

<ImageView

android:id=“@+id/iv_system”

android:layout_width=“20dp”

android:layout_height=“20dp”

android:layout_alignParentEnd=“true”

android:layout_centerVertical=“true”

android:layout_marginEnd=“24dp”

android:padding=“2dp”

android:src=“@drawable/ic_check” />

<RelativeLayout

android:id=“@+id/lay_chinese”

android:layout_width=“match_parent”

android:layout_height=“48dp”

android:layout_marginTop=“1dp”

android:background=“#FFF”

android:gravity=“center_vertical”>

<TextView

android:layout_width=“wrap_content”

android:layout_height=“match_parent”

android:layout_marginStart=“16dp”

android:gravity=“center”

android:text=“@string/chinese”

android:textColor=“#4A4A4A”

android:textSize=“14sp” />

<ImageView

android:id=“@+id/iv_chinese”

android:layout_width=“20dp”

android:layout_height=“20dp”

android:layout_alignParentEnd=“true”

android:layout_centerVertical=“true”

android:layout_marginEnd=“24dp”

android:padding=“2dp”

android:src=“@drawable/ic_check”

android:visibility=“gone” />

<RelativeLayout

android:id=“@+id/lay_english”

android:layout_width=“match_parent”

android:layout_height=“48dp”

android:layout_marginTop=“1dp”

android:background=“#FFF”

android:gravity=“center_vertical”>

<TextView

android:layout_width=“wrap_content”

android:layout_height=“match_parent”

android:layout_marginStart=“16dp”

android:gravity=“center”

android:text=“@string/english”

android:textColor=“#4A4A4A”

android:textSize=“14sp” />

<ImageView

android:id=“@+id/iv_english”

android:layout_width=“20dp”

android:layout_height=“20dp”

android:layout_alignParentEnd=“true”

android:layout_centerVertical=“true”

android:layout_marginEnd=“24dp”

android:padding=“2dp”

android:src=“@drawable/ic_check”

android:visibility=“gone” />

<RelativeLayout

android:id=“@+id/lay_traditional_chinese”

android:layout_width=“match_parent”

android:layout_height=“48dp”

android:layout_marginTop=“1dp”

android:background=“#FFF”

android:gravity=“center_vertical”>

<TextView

android:layout_width=“wrap_content”

android:layout_height=“match_parent”

android:layout_marginStart=“16dp”

android:gravity=“center”

android:text=“@string/traditional_chinese”

android:textColor=“#4A4A4A”

android:textSize=“14sp” />

<ImageView

android:id=“@+id/iv_traditional_chinese”

android:layout_width=“20dp”

android:layout_height=“20dp”

android:layout_alignParentEnd=“true”

android:layout_centerVertical=“true”

android:layout_marginEnd=“24dp”

android:padding=“2dp”

android:src=“@drawable/ic_check”

android:visibility=“gone” />

三个Activity的页面都写好了,下面改动一下代码。

首先是MainActivity。在MainActivity中去继承BaseActivity,然后实现控件的点击事件监听。

package com.llw.language;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;

import android.os.Bundle;

import android.os.LocaleList;

import android.util.Log;

import android.view.View;

import android.widget.ImageView;

import android.widget.TextView;

import java.util.Locale;

/**

  • 主页面

  • @author llw

*/

public class MainActivity extends BaseActivity implements View.OnClickListener {

private TextView tvSystemLanguage;//系统语言

private TextView tvCurrentLanguage;//当前语言

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

ImageView imageView = findViewById(R.id.iv_setting);

TextView tvOtherPage = findViewById(R.id.tv_other_pages);

tvSystemLanguage = findViewById(R.id.tv_sys_language);

tvCurrentLanguage = findViewById(R.id.tv_cur_language);

imageView.setOnClickListener(this);

tvOtherPage.setOnClickListener(this);

}

@Override

public void onClick(View v) {

switch (v.getId()) {

case R.id.iv_setting://进入设置页面

goToActivity(SettingActivity.class);

break;

case R.id.tv_other_pages://进入其他页面

goToActivity(OtherActivity.class);

break;

default:

break;

}

}

/**

  • 跳转页面

  • @param clazz 目标Activity

*/

private void goToActivity(Class<?> clazz) {

startActivity(new Intent(this,clazz));

}

}

再来看。OtherActivity。

package com.llw.language;

import androidx.appcompat.widget.Toolbar;

import android.os.Bundle;

/**

  • 其他页面

  • @author llw

*/

public class OtherActivity extends BaseActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_other);

Toolbar toolbar = findViewById(R.id.toolbar);

Back(toolbar);

}

}

最后是SettingActivity。

package com.llw.language;

import androidx.appcompat.widget.Toolbar;

import android.os.Bundle;

/**

  • 设置页面

  • @author llw

*/

public class SettingActivity extends BaseActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_setting);

Toolbar toolbar = findViewById(R.id.toolbar);

Back(toolbar);

}

}

下面你就可以运行了,无论你是运行在虚拟器还是手机,都可以。AS中默认下载的模拟器打开之后是英文的,因此刚来可以测试一下这个APP是否会适配Android系统语言。

在这里插入图片描述

OK,已经适配了,那么接下来用自己的手机来运行一下,看是不是会显示中文。(如果自己的手机默认是英文的语言,我只能说你是个人才)

在这里插入图片描述

点击跳转其他页面或者设置页面也都是中文的,我这里就不一一截图了。

刚才不是还有一个繁体的吗?那么将自己手机的语言改成繁体,再打开这个APP,看看会怎么样。更改Android系统需要,通常在手机的设置里面,然后在设置里面找到有系统相关的选项。再找到语言相关的选项。之后选择语言和地区,然后切换一下语言看看。

在这里插入图片描述

我现在已经切换到繁体了,然后再打开APP。

在这里插入图片描述

呐,没骗你吧。骗倒是没骗我,不过,这难道就是多语言吗?只是配置了多个语言文件就可以了吗?

那当然不是,你要知道这种方式适合一般的用户使用,是没有问题的。而某些用户为了装个逼,明明系统语言是中文的,但是它要求你APP要有英文、日文、法文等一些语言。这个时候你再根据系统来设置就不合适了,因为不都不认识,多了改变资源文件只是在适配Android系统中改动的语言,而对于App中修改语言还要进一步改进才行。

五、工具类


刚才是通过改变系统语言进而改变APP页面,下面是不改变系统语言也要改变APP语言。

做过Android应用开发的相信对Application是不陌生的,常规的是通过写一个自定义的Applictaion,比如BaseApplication,然后继承自Application。然后在BaseApplication中进行一些应用的初始化操作之类。而既然是改动APP的语言,那么肯定是和这个Applictaion是有关系的。

下面新建一个utils包,包下新建一个SPUtils类。代码如下:

package com.llw.language.utils;

import android.content.Context;

import android.content.SharedPreferences;

import java.util.Locale;

/**

  • 语言缓存工具类

  • @author llw

*/

public class SPUtils {

private final String SP_NAME = “language_setting”;//缓存名称

private final String TAG_LANGUAGE = “language_select”;

private static volatile SPUtils instance;

private final SharedPreferences mSharedPreferences;

private Locale systemCurrentLocal = Locale.CHINESE;//系统当前本地语言为中文 初始值

public SPUtils(Context context) {

//通过上下文获取本地缓存

mSharedPreferences = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);

}

/**

  • 设置语言

  • @param select 选中的语言项

*/

public void setLanguage(int select) {

//缓存编辑者

SharedPreferences.Editor editor = mSharedPreferences.edit();

//放入保存的语言项

editor.putInt(TAG_LANGUAGE, select);

//提交 之后 缓存语言项保存完毕

editor.commit();

}

/**

  • 获取语言

  • @return 从缓存中根据缓存名或者缓存值,如果没有,则返回默认值0

*/

public int getLanguage() {

return mSharedPreferences.getInt(TAG_LANGUAGE, 0);

}

/**

  • 设置系统当前本地

  • @param local 本地对象

*/

public void setSystemCurrentLocal(Locale local) {

systemCurrentLocal = local;

}

/**

  • 获取系统当前本地

  • @return 系统当前本地

*/

public Locale getSystemCurrentLocal() {

return systemCurrentLocal;

}

/**

  • 获取实例

  • @param context 上下文参数

  • @return SPUtils实例对象

*/

public static SPUtils getInstance(Context context) {

if (instance == null) {//等于空则重新创建实例,不为空则直接返回

synchronized (SPUtils.class) {//增加一个同步锁,如果已经有了实例则跳出

if (instance == null) {

//创建新的对象

instance = new SPUtils(context);

}

}

}

return instance;

}

}

下面是另一个工具类LocalManageUtils,代码如下:

package com.llw.language.utils;

import android.content.Context;

import android.content.res.Configuration;

import android.content.res.Resources;

import android.os.Build;

import android.os.LocaleList;

import android.util.Log;

import com.llw.language.R;

import java.util.Locale;

/**

  • 本地管理工具类

  • @author llw

*/

public class LocalManageUtils {

private static final String TAG = “LocalManage”;

/**

  • 获取系统的 locale对象

  • @param context 上下文参数

  • @return locale对象

*/

public static Locale getSystemLocal(Context context) {

return SPUtils.getInstance(context).getSystemCurrentLocal();

}

/**

  • 获取当前APP使用的语言

  • @param context 上下文参数

  • @return 语言类型描述

*/

public static String getSelectLanguage(Context context) {

//根据缓存中的语言返回当前设置的语言类型文字

switch (SPUtils.getInstance(context).getLanguage()) {

case 0:

return context.getString(R.string.system_lang);

case 1:

return context.getString(R.string.chinese);

case 2:

return context.getString(R.string.english);

case 3:

return context.getString(R.string.traditional_chinese);

default:

return context.getString(R.string.chinese);

}

}

/**

  • 获取选择的语言设置

  • @param context 上下文参数

  • @return locale

*/

public static Locale getSelectLanguageLocal(Context context) {

switch (SPUtils.getInstance(context).getLanguage()) {

case 0:

return getSystemLocal(context);//系统语言

case 1:

return Locale.CHINESE;//中文

case 2:

return Locale.ENGLISH;//英文

case 3:

return Locale.TRADITIONAL_CHINESE;//中文繁体

default:

return Locale.CHINESE;//中文

}

}

/**

  • 设置选中的语言

  • @param context 上下文参数

  • @param select 选中的语言项

*/

public static void setSelectLanguage(Context context, int select) {

//放入缓存中

SPUtils.getInstance(context).setLanguage(select);

//设置APP语言

setAppLanguage(context);

}

/**

  • 设置App语言

  • @param context

*/

public static void setAppLanguage(Context context) {

//通过应用全局上下文获取资源对象

Resources resources = context.getApplicationContext().getResources();

//获取资源配置对象

Configuration config = resources.getConfiguration();

//获取系统本地对象

Locale locale = getSelectLanguageLocal(context);

//配置本地资源

config.setLocale(locale);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//Android7.0及以上

//获取本地语言列表

LocaleList localeList = new LocaleList(locale);

//设置默认语言列表

LocaleList.setDefault(localeList);

//设置语言环境列表

config.setLocales(localeList);

//创建配置系统的上下文参数

context.getApplicationContext().createConfigurationContext(config);

//设置默认语言

Locale.setDefault(locale);

}

//更新资源配置

resources.updateConfiguration(config, resources.getDisplayMetrics());

}

/**

  • 设置本地语言

  • @param context 上下文参数

  • @return 设置后的对象

*/

public static Context setLocale(Context context) {

return updateResource(context, getSelectLanguageLocal(context));

}

/**

  • 更新资源

  • @param context 上下文参数

  • @param locale 本地语言

  • @return

*/

private static Context updateResource(Context context, Locale locale) {

//设置默认语言

Locale.setDefault(locale);

//通过上下文获取资源对象

Resources resources = context.getResources();

//资源配置对象

Configuration config = new Configuration(resources.getConfiguration());

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {//Android4.2及以上

//设置语言

config.setLocale(locale);

//获取设置之后的上下文参数

context = context.createConfigurationContext(config);

} else {

//配置语言

config.setLocale(locale);

//更新资源配置

resources.updateConfiguration(config, resources.getDisplayMetrics());

}

return context;

}

/**

  • 设置系统当前语言

  • @param context

*/

public static void setSystemCurrentLanguage(Context context) {

Locale locale;

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//Android7.0及以上

locale = LocaleList.getDefault().get(0);

} else {

locale = Locale.getDefault();

}

Log.d(TAG, locale.getLanguage());

//设置应用当前本地语言

SPUtils.getInstance(context).setSystemCurrentLocal(locale);

}

/**

  • 更改应用配置

  • @param context 上下文参数

*/

public static void onConfigurationChanged(Context context) {

setSystemCurrentLanguage(context);

setLocale(context);

setAppLanguage(context);

}

}

里面的方法都是有注释的,也都是比较简单的方法,这里就不过多的解释了。

上面的LocalManageUtils中最多的参数是Context,上下文参数平时通常是在Activity、Service、Fragment等一些组件中使用,那你有没有想过这些组件中的Context是怎么来的,常规的都是这些组件的生命周期,你突然说Context是怎么来的?这就触及到我的知识盲区了。首先Activity的这个上下文参数是怎么来的,这里可以重写一个方法。

比如在BaseActivity中,通过重写attachBaseContext方法,对Actiivty附加基础上下文,里面使用父类的attachBaseContext方法。

@Override

protected void attachBaseContext(Context newBase) {

super.attachBaseContext(newBase);

}

那么它的父类是谁呢?很显然之前我继承了AppCompatActivity。那么肯定就是这个里面,那么再进去里面看看。

在这里插入图片描述

你会发现怎么这里面又调用了父类的attachBaseContext方法,那就还得再找下去,你会发现AppCompatActivity最终继承自Activity(中间省略若干个Activity),子类继承父类,一般来说都是为了拓展,那么为什么要拓展,而不是在原来的基础上改呢?因为要适配。都知道Android的版本有很多,很多古老的版本现在都见不到了,但是Google仍然要去适配,因为那些低版本的Android系统现在不一定还在手机上,但是Android系统又不是只有手机的产品,还有其他的,比如TV、智能穿戴,这些设备的Android版本通常不高,因为更多的是做定制的。所以Android版本级别越低得到的权限就越多,改起来越简单。

在这里插入图片描述

然后你会发现Activity继承自ContextThemeWrapper,同样在调用了父类ContextThemeWrapper的attachBaseContext。

在这里插入图片描述

而ContextThemeWrapper又继承了ContextWrapper,它里面也是调用父类ContextWrapper的attachBaseContext。

在这里插入图片描述

在ContextWrapper这里终于不再调用父类了。累坏了吧,喝口水歇歇。

在这里可以看看有哪些类使用了attachBaseContext。哪些类就能拿到上下文参数。

在这里插入图片描述

你有没有发现,这里并没有看到Fragment,因为Fragment是依附在Actiivty上的。而ContextWrapper 继承了底层的Context,Context本身是一个抽象类,所以ContextWrapper 就是它的实现类,在这个实现类中,获取上下文,然后通过层层的继承和封装就传到了Activity。

嗯!有理有据,不过你说了半天这个Context的意义在哪里呢?它的意义就在于它可以改变应用和页面的资源配置。而当页面的资源配置发生改变时,就会调用attachBaseContext方法重新配置上下文,以达到切换资源配置的目的,就像切换语言这样。这么说你是否有一些明白呢?

六、配置页面和应用的上下文


刚才说了这么多理论的东西,手痒难耐了吧,来动手实践一下吧。之前在BaseActivity中重写了attachBaseContext,然后里面调用父类的attachBaseContext,然后传了一个上下文参数进去,而我就是要对这个参数动手脚。

@Override

protected void attachBaseContext(Context newBase) {

super.attachBaseContext(LocalManageUtils.setLocale(newBase));

}

这里调用了LocalManageUtils的setLocale方法。

/**

  • 设置本地语言

  • @param context 上下文参数

  • @return 设置后的对象

*/

public static Context setLocale(Context context) {

return updateResource(context, getSelectLanguageLocal(context));

}

这个方法就是通过附加上下文时,改变上下文的一些配置,然后再返回上下文,这时这个上下文才会也页面生效。而我所有的Activity都继承自BaseActivity,那么它就对所有的Activity也生效。

而这还不够,因为现在你只是改变了页面而已,还没有改变这个App,那么怎么改变整个App呢?当然需要这个Application。

来看看这个自定义的BaseApplication。

package com.llw.language;

import android.app.Application;

import android.content.Context;

import android.content.res.Configuration;

import android.util.Log;

import androidx.annotation.NonNull;

import com.llw.language.utils.LocalManageUtils;

/**

  • 自定义基础Application

  • @author llw

*/

public class BaseApplication extends Application {

public static final String TAG = “BaseApplication”;

@Override

protected void attachBaseContext(Context base) {

//设置系统当前语言

LocalManageUtils.setSystemCurrentLanguage(base);

super.attachBaseContext(LocalManageUtils.setLocale(base));

Log.d(TAG,“attachBaseContext”);

}

@Override

public void onCreate() {

super.onCreate();

//设置App的语言

LocalManageUtils.setAppLanguage(this);

Log.d(TAG,“onCreate”);

}

@Override

public void onConfigurationChanged(@NonNull Configuration newConfig) {

super.onConfigurationChanged(newConfig);

//通过全局的上下文参数更改相关资源配置

LocalManageUtils.onConfigurationChanged(getApplicationContext());

Log.d(TAG,“onConfigurationChanged”);

}

}

尾声

评论里面有些同学有疑问关于如何学习material design控件,我的建议是去GitHub搜,有很多同行给的例子,这些栗子足够入门。

有朋友说要是动真格的话,需要NDK以及JVM等的知识,首现**NDK并不是神秘的东西,**你跟着官方的步骤走一遍就知道什么回事了,无非就是一些代码格式以及原生/JAVA内存交互,进阶一点的有原生/JAVA线程交互,线程交互确实有点蛋疼,但平常避免用就好了,再说对于初学者来说关心NDK干嘛,据鄙人以前的经历,只在音视频通信和一个嵌入式信号处理(离线)的两个项目中用过,嵌入式信号处理是JAVA->NDK->.SO->MATLAB这样调用的我原来MATLAB的代码,其他的大多就用在游戏上了吧,一般的互联网公司会有人给你公司的SO包的。
至于JVM,该掌握的那部分,相信我,你会掌握的,不该你掌握的,有那些专门研究JVM的人来做,不如省省心有空看看计算机系统,编译原理。

一句话,平常多写多练,这是最基本的程序员的素质,尽量挤时间,读理论基础书籍,JVM不是未来30年唯一的虚拟机,JAVA也不一定再风靡未来30年工业界,其他的系统和语言也会雨后春笋冒出来,但你理论扎实会让你很快理解学会一个语言或者框架,你平常写的多会让你很快熟练的将新学的东西应用到实际中。
初学者,一句话,多练。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

/**

  • 自定义基础Application

  • @author llw

*/

public class BaseApplication extends Application {

public static final String TAG = “BaseApplication”;

@Override

protected void attachBaseContext(Context base) {

//设置系统当前语言

LocalManageUtils.setSystemCurrentLanguage(base);

super.attachBaseContext(LocalManageUtils.setLocale(base));

Log.d(TAG,“attachBaseContext”);

}

@Override

public void onCreate() {

super.onCreate();

//设置App的语言

LocalManageUtils.setAppLanguage(this);

Log.d(TAG,“onCreate”);

}

@Override

public void onConfigurationChanged(@NonNull Configuration newConfig) {

super.onConfigurationChanged(newConfig);

//通过全局的上下文参数更改相关资源配置

LocalManageUtils.onConfigurationChanged(getApplicationContext());

Log.d(TAG,“onConfigurationChanged”);

}

}

尾声

评论里面有些同学有疑问关于如何学习material design控件,我的建议是去GitHub搜,有很多同行给的例子,这些栗子足够入门。

有朋友说要是动真格的话,需要NDK以及JVM等的知识,首现**NDK并不是神秘的东西,**你跟着官方的步骤走一遍就知道什么回事了,无非就是一些代码格式以及原生/JAVA内存交互,进阶一点的有原生/JAVA线程交互,线程交互确实有点蛋疼,但平常避免用就好了,再说对于初学者来说关心NDK干嘛,据鄙人以前的经历,只在音视频通信和一个嵌入式信号处理(离线)的两个项目中用过,嵌入式信号处理是JAVA->NDK->.SO->MATLAB这样调用的我原来MATLAB的代码,其他的大多就用在游戏上了吧,一般的互联网公司会有人给你公司的SO包的。
至于JVM,该掌握的那部分,相信我,你会掌握的,不该你掌握的,有那些专门研究JVM的人来做,不如省省心有空看看计算机系统,编译原理。

一句话,平常多写多练,这是最基本的程序员的素质,尽量挤时间,读理论基础书籍,JVM不是未来30年唯一的虚拟机,JAVA也不一定再风靡未来30年工业界,其他的系统和语言也会雨后春笋冒出来,但你理论扎实会让你很快理解学会一个语言或者框架,你平常写的多会让你很快熟练的将新学的东西应用到实际中。
初学者,一句话,多练。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 24
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值