2024年安卓最新Android 11 Settings源码入门,android多线程面试题

学习分享

在当下这个信息共享的时代,很多资源都可以在网络上找到,只取决于你愿不愿意找或是找的方法对不对了

很多朋友不是没有资料,大多都是有几十上百个G,但是杂乱无章,不知道怎么看从哪看起,甚至是看后就忘

如果大家觉得自己在网上找的资料非常杂乱、不成体系的话,我也分享一套给大家,比较系统,我平常自己也会经常研读。

2021最新上万页的大厂面试真题

七大模块学习资料:如NDK模块开发、Android框架体系架构…

只有系统,有方向的学习,才能在段时间内迅速提高自己的技术。

这份体系学习笔记,适应人群:
**第一,**学习知识比较碎片化,没有合理的学习路线与进阶方向。
**第二,**开发几年,不知道如何进阶更进一步,比较迷茫。
**第三,**到了合适的年纪,后续不知道该如何发展,转型管理,还是加强技术研究。

由于文章内容比较多,篇幅不允许,部分未展示内容以截图方式展示 。

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

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

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

其中:

  • key:该配置项的主键
  • title:配置项的标题
  • summary:概要标题下面的文字
  • icon:前面的图标
  • order:用来做排序的,值越小则排行越靠前
  • fragment:点击该item要跳转的界面
  • controller:该item的控制器,控制它的内容展示,是否可用,也可以控制它的点击事件
2,动态添加

动态获取是根据特殊的action标记,通过packageManger查询系统中安装的符合对应action的应用,将其动态添加到列表中。

例如:网络流量监控,存储空间管理,默认应用等配置项都是动态添加的。

具体实现可以参看文章:MTK快霸是如何动态加载的

二,系统设置其他界面

系统设置中除了.homepage.SettingsHomepageActivity,其他大部分的Activity都定义在Settings中, 并且继承自SettingsActivity, 但其中并没有实现任何逻辑。因此,这些Activity的逻辑都是在SettingsActivity中实现。

/**

  • Top-level Settings activity
    */
    public class Settings extends SettingsActivity {

/*

  • Settings subclasses for launching independently.
    /
    public static class AssistGestureSettingsActivity extends SettingsActivity { /
    empty /}
    public static class BluetoothSettingsActivity extends SettingsActivity { /
    empty / }
    public static class CreateShortcutActivity extends SettingsActivity { /
    empty / }
    public static class FaceSettingsActivity extends SettingsActivity { /
    empty / }
    public static class FingerprintSettingsActivity extends SettingsActivity { /
    empty */ }

    }

这些Activity中并没有实现任何逻辑,那它是怎么加载到自己应有的布局的呢?

在父类SettingsActivityonCreate()中:

@Override
protected void onCreate(Bundle savedState) {


// Should happen before any call to getIntent()
// 第一步
getMetaData();
// 第二步
final Intent intent = getIntent();
if (intent.hasExtra(EXTRA_UI_OPTIONS)) {
getWindow().setUiOptions(intent.getIntExtra(EXTRA_UI_OPTIONS, 0));
}

// Getting Intent properties can only be done after the super.onCreate(…)
final String initialFragmentName = intent.getStringExtra(EXTRA_SHOW_FRAGMENT);

// 第三步
launchSettingFragment(initialFragmentName, intent);


}

跟着上面的三个步骤:

第一步

首先通过getMetaData()获取该Activity在manifest中配置的fragment, 并赋值给mFragmentClass

public static final String META_DATA_KEY_FRAGMENT_CLASS = “com.android.settings.FRAGMENT_CLASS”;

private void getMetaData() {
try {
ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),
PackageManager.GET_META_DATA);
if (ai == null || ai.metaData == null) return;
mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
} catch (NameNotFoundException nnfe) {
// No recovery
Log.d(LOG_TAG, "Cannot get Metadata for: " + getComponentName().toString());
}
}

那么manifest中是怎么配置的呢?如下:

由此可知WifiInfoActivity这个Acitivity对应的fragment是:com.android.settings.wifi.WifiInfo

第二步

通过getIntent()构造包含EXTRA_SHOW_FRAGMENT的intent

public Intent getIntent() {
Intent superIntent = super.getIntent();
String startingFragment = getStartingFragmentClass(superIntent);
// This is called from super.onCreate, isMultiPane() is not yet reliable
// Do not use onIsHidingHeaders either, which relies itself on this method
if (startingFragment != null) {
Intent modIntent = new Intent(superIntent);
modIntent.putExtra(EXTRA_SHOW_FRAGMENT, startingFragment);
Bundle args = superIntent.getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
if (args != null) {
args = new Bundle(args);
} else {
args = new Bundle();
}
args.putParcelable(“intent”, superIntent);
modIntent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args);
return modIntent;
}
return superIntent;
}

/**

  • Checks if the component name in the intent is different from the Settings class and
  • returns the class name to load as a fragment.
    */
    private String getStartingFragmentClass(Intent intent) {
    // 存在mFragmentClass则直接返回
    if (mFragmentClass != null) return mFragmentClass;

String intentClass = intent.getComponent().getClassName();
if (intentClass.equals(getClass().getName())) return null;

if (“com.android.settings.RunningServices”.equals(intentClass)
|| “com.android.settings.applications.StorageUse”.equals(intentClass)) {
// Old names of manage apps.
intentClass = ManageApplications.class.getName();
}

return intentClass;
}

这里包含了mFragmentClass为空的情况,暂时先不管。

第三步

通过launchSettingFragment()启动对应Fragment,这里的initialFragmentName参数就是第二步Intent中包含的EXTRA_SHOW_FRAGMENT参数,mFragmentClass不为空的情况下传入的就是mFragmentClass

void launchSettingFragment(String initialFragmentName, Intent intent) {
if (initialFragmentName != null) {
setTitleFromIntent(intent);

Bundle initialArguments = intent.getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
switchToFragment(initialFragmentName, initialArguments, true,
mInitialTitleResId, mInitialTitle);
} else {
// Show search icon as up affordance if we are displaying the main Dashboard
mInitialTitleResId = R.string.dashboard_title;
switchToFragment(TopLevelSettings.class.getName(), null /* args */, false,
mInitialTitleResId, mInitialTitle);
}
}

switchToFragment()中将fragment添加到activity中。

/**

  • Switch to a specific Fragment with taking care of validation, Title and BackStack
    */
    private Fragment switchToFragment(String fragmentName, Bundle args, boolean validate,
    int titleResId, CharSequence title) {
    Log.d(LOG_TAG, "Switching to fragment " + fragmentName);
    if (validate && !isValidFragment(fragmentName)) {
    throw new IllegalArgumentException("Invalid fragment for this activity: "
  • fragmentName);
    }
    // 反射创建fragment
    Fragment f = Utils.getTargetFragment(this, fragmentName, args);
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.replace(R.id.main_content, f);
    if (titleResId > 0) {
    transaction.setBreadCrumbTitle(titleResId);
    } else if (title != null) {
    transaction.setBreadCrumbTitle(title);
    }
    // 提交事务
    transaction.commitAllowingStateLoss();
    getSupportFragmentManager().executePendingTransactions();
    Log.d(LOG_TAG, “Executed frag manager pendingTransactions”);
    return f;
    }
三,数据控制

在首页-电池设置项中可以显示实时电量。那么它是如果实现的呢?

首先看下它是如何配置的:

配置项中配置了TopLevelBatteryPreferenceController控制器,它继承自AbstractPreferenceController,这个抽象类用于对所有菜单项进行统一管理(例如展示或隐藏,监听点击事件等)。

TopLevelBatteryPreferenceController代码如下:

public class TopLevelBatteryPreferenceController extends BasePreferenceController implements
LifecycleObserver, OnStart, OnStop {

// 电量改变广播
private final BatteryBroadcastReceiver mBatteryBroadcastReceiver;
// 当前配置项
private Preference mPreference;

最后

针对于上面的问题,我总结出了互联网公司Android程序员面试涉及到的绝大部分面试题及答案,并整理做成了文档,以及系统的进阶学习视频资料。
(包括Java在Android开发中应用、APP框架知识体系、高级UI、全方位性能调优,NDK开发,音视频技术,人工智能技术,跨平台技术等技术资料),希望能帮助到你面试前的复习,且找到一个好的工作,也节省大家在网上搜索资料的时间来学习。

image

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

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

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

[外链图片转存中…(img-ImwRACAJ-1715768337656)]

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

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

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值