2024年最全Android Framework学习笔记(十)Content Provider启动过程,面试官看完简历后什么都没说

总结

最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的Android开发中高级必知必会核心笔记,共计2968页PDF、58w字,囊括Android开发648个知识点,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

2021年虽然路途坎坷,都在说Android要没落,但是,不要慌,做自己的计划,学自己的习,竞争无处不在,每个行业都是如此。相信自己,没有做不到的,只有想不到的。

虽然面试失败了,但我也不会放弃入职字节跳动的决心的!建议大家面试之前都要有充分的准备,顺顺利利的拿到自己心仪的offer。

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

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

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

}

holder = installProvider(c, holder, holder.info,

true /noisy/, holder.noReleaseNeeded, stable); //3

return holder.provider;

}

注释1处检查ActivityThread中的ArrayMap类型的mProviderMap中是否有目标ContentProvider存在,有则返回,没有就会在注释2处调用AMP的getContentProvider方法,最终会调用AMS的getContentProvider方法。

注释3处的installProvider方法用来将注释2处返回的ContentProvider相关的数据存储在mProviderMap中,起到缓存的作用,这样使用相同的Content Provider时,就不需要每次都要调用AMS的getContentProvider方法。

AMS到ActivityThread的调用


frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

ActivityManagerService#getContentProvider()

@Override

public final ContentProviderHolder getContentProvider(

IApplicationThread caller, String name, int userId, boolean stable) {

return getContentProviderImpl(caller, name, null, stable, userId);

}

ActivityManagerService#getContentProviderImpl()

private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,

String name, IBinder token, boolean stable, int userId) {

ProcessRecord proc = getProcessRecordLocked(

cpi.processName, cpr.appInfo.uid, false); //1

if (proc != null && proc.thread != null && !proc.killed) {

if (!proc.pubProviders.containsKey(cpi.name)) {

checkTime(startTime, “getContentProviderImpl: scheduling install”);

proc.pubProviders.put(cpi.name, cpr);

try {

proc.thread.scheduleInstallProvider(cpi); //2

} catch (RemoteException e) {

}

}

} else {

checkTime(startTime, “getContentProviderImpl: before start process”);

proc = startProcessLocked(cpi.processName,

cpr.appInfo, false, 0, “content provider”,

new ComponentName(cpi.applicationInfo.packageName,

cpi.name), false, false, false); //3

checkTime(startTime, “getContentProviderImpl: after start process”);

}

}

注释1处通过getProcessRecordLocked方法来获取目标ContentProvider的应用程序进程信息,这些信息用ProcessRecord类型的proc来表示,如果该应用进程已经启动就会调用注释2处的代码,否则就会调用注释3的startProcessLocked方法来启动进程。

应用程序进程启动过程请参考Framework学习(六)应用程序进程启动过程这篇文章。

ActivityThread启动Provider


frameworks/base/services/core/java/com/android/app/ActivityThread.java

ActivityThread#scheduleInstallProvider()

@Override

public void scheduleInstallProvider(ProviderInfo provider) {

sendMessage(H.INSTALL_PROVIDER, provider);

}

这里的H是ActivityThread的内部类并继承Handler。

ActivityThread.H


private class H extends Handler {

public static final int INSTALL_PROVIDER = 145;

public void handleMessage(Message msg) {

if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));

switch (msg.what) {

case INSTALL_PROVIDER:

handleInstallProvider((ProviderInfo) msg.obj);

break;

}

ActivityThread#handleInstallProvider()

public void handleInstallProvider(ProviderInfo info) {

final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();

try {

installContentProviders(mInitialApplication, Lists.newArrayList(info)); //1

} finally {

StrictMode.setThreadPolicy(oldPolicy);

}

}

注释1调用了installContentProviders方法。

ActivityThread#installContentProviders()

private void installContentProviders(

Context context, List providers) {

final ArrayList<IActivityManager.ContentProviderHolder> results =

new ArrayList<IActivityManager.ContentProviderHolder>();

for (ProviderInfo cpi : providers) { //1

if (DEBUG_PROVIDER) {

StringBuilder buf = new StringBuilder(128);

buf.append("Pub ");

buf.append(cpi.authority);

buf.append(": ");

buf.append(cpi.name);

Log.i(TAG, buf.toString());

}

IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi,

false /noisy/, true /noReleaseNeeded/, true /stable/); //2

if (cph != null) {

cph.noReleaseNeeded = true;

results.add(cph);

}

}

try {

ActivityManagerNative.getDefault().publishContentProviders(

getApplicationThread(), results); //3

} catch (RemoteException ex) {

throw ex.rethrowFromSystemServer();

}

}

注释1处遍历当前应用程序进程的ProviderInfo列表,得到每个Content Provider的ProviderInfo(存储Content Provider的信息)。

注释2处调用installProvider方法来启动这些Content Provider。

注释3处通过AMS的publishContentProviders方法将这些Content Provider存储在AMS的mProviderMap中,这个mProviderMap在前面提到过,起到缓存的作用,防止每次使用相同的Content Provider时都会调用AMS的getContentProvider方法。

ActivityThread#installProvider()

private IActivityManager.ContentProviderHolder installProvider(Context context,

IActivityManager.ContentProviderHolder holder, ProviderInfo info,

boolean noisy, boolean noReleaseNeeded, boolean stable) {

ContentProvider localProvider = null;

final java.lang.ClassLoader cl = c.getClassLoader();

localProvider = (ContentProvider)cl.

loadClass(info.name).newInstance(); //1

provider = localProvider.getIContentProvider();

if (provider == null) {

return null;

}

if (DEBUG_PROVIDER) Slog.v(

TAG, "Instantiating local provider " + info.name);

localProvider.attachInfo(c, info); //2

} catch (java.lang.Exception e) {

}

return null;

}

}

return retHolder;

}

注释1处通过反射来创建ContentProvider类型的localProvider对象。

注释2处调用了它的attachInfo方法。

frameworks/base/core/java/android/content/ContentProvider.java

ContentProvider#attachInfo()


public void attachInfo(Context context, ProviderInfo info) {

attachInfo(context, info, false);

}

private void attachInfo(Context context, ProviderInfo info, boolean testing) {

mNoPerms = testing;

/*

  • Only allow it to be set once, so after the content service gives

  • this to us clients can’t change it.

*/

if (mContext == null) {

mContext = context;

if (context != null) {

mTransport.mAppOpsManager = (AppOpsManager) context.getSystemService(

Context.APP_OPS_SERVICE);

}

mMyUid = Process.myUid();

if (info != null) {

setReadPermission(info.readPermission);

setWritePermission(info.writePermission);

setPathPermissions(info.pathPermissions);

mExported = info.exported;

mSingleUser = (info.flags & ProviderInfo.FLAG_SINGLE_USER) != 0;

setAuthorities(info.authority);

}

ContentProvider.this.onCreate(); //1

}

}

总结:

面试是一个不断学习、不断自我提升的过程,有机会还是出去面面,至少能想到查漏补缺效果,而且有些知识点,可能你自以为知道,但让你说,并不一定能说得很好。

有些东西有压力才有动力,而学到的知识点,都是钱(因为技术人员大部分情况是根据你的能力来定级、来发薪水的),技多不压身。

附上我的面试各大专题整理: 面试指南,满满的都是干货,希望对大家有帮助!

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

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

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

//1

}

}

总结:

面试是一个不断学习、不断自我提升的过程,有机会还是出去面面,至少能想到查漏补缺效果,而且有些知识点,可能你自以为知道,但让你说,并不一定能说得很好。

有些东西有压力才有动力,而学到的知识点,都是钱(因为技术人员大部分情况是根据你的能力来定级、来发薪水的),技多不压身。

附上我的面试各大专题整理: 面试指南,满满的都是干货,希望对大家有帮助!
[外链图片转存中…(img-mEypvYrK-1715112910787)]

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值