Arouter讲解4_Core,android高级工程师面试题及答案

provider.init(mContext);
Warehouse.providers.put(providerMeta, provider); // 放到缓存中
instance = provider;
} catch (Exception e) {
logger.error(TAG, “Init provider failed!”, e);
throw new HandlerException(“Init provider failed!”);
}
}
postcard.setProvider(instance); // 拿到了实例对象
postcard.greenChannel(); // 绿色通道, Provider不受拦截器的影响
break;
case FRAGMENT:
postcard.greenChannel(); // Fragment 类型也走绿色通道,不受拦截器的影响
default:
break;
}
}
}

build

public Postcard build(String path) {
return _ARouter.getInstance().build(path);
}

我们用build进行源码分析,首先

protected Postcard build(String path) {
if (TextUtils.isEmpty(path)) {
throw new HandlerException(Consts.TAG + “Parameter is invalid!”);
} else {
PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
if (null != pService) {
path = pService.forString(path);
}
// 如果有PathReplaceService ,这里的path已经经过PathReplaceService, afterReplace就是为true,后面就不要到 PathReplaceService了
return build(path, extractGroup(path), true);
}
}

如果实现 PathReplaceService ,可以对path进行拦截与修改。

public interface PathReplaceService extends IProvider {

/**

  • For normal path.
  • @param path raw path
    */
    String forString(String path);

/**

  • For uri type.
  • @param uri raw uri
    */
    Uri forUri(Uri uri);
    }

protected Postcard build(String path, String group, Boolean afterReplace) {
if (TextUtils.isEmpty(path) || TextUtils.isEmpty(group)) {
throw new HandlerException(Consts.TAG + “Parameter is invalid!”);
} else {
if (!afterReplace) {
PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
if (null != pService) {
path = pService.forString(path);
}
}
return new Postcard(path, group);
}
}

protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {

// 在 navigation之前 我们还有一次机会修改Postcard,是否需要被路由
PretreatmentService pretreatmentService = ARouter.getInstance().navigation(PretreatmentService.class);
if (null != pretreatmentService && !pretreatmentService.onPretreatment(context, postcard)) {
// 条件不满足,不再 navigation
// Pretreatment failed, navigation canceled.
return null;
}

// Set context to postcard.
postcard.setContext(null == context ? mContext : context);

try {
LogisticsCenter.completion(postcard); // 把数据填充到 Postcard
} catch (NoRouteFoundException ex) {

if (null != callback) {
callback.onLost(postcard);//给出回调
} else {
// No callback for this invoke, then we use the global degrade service.
DegradeService degradeService = ARouter.getInstance().navigation(DegradeService.class);
if (null != degradeService) {
degradeService.onLost(context, postcard);
}
}

return null;
}

if (null != callback) {
callback.onFound(postcard); //给出回调,已经找到 postcard
}

// Arouter init后,会获取 InterceptorService
if (!postcard.isGreenChannel()) { // It must be run in async thread, maybe interceptor cost too mush time made ANR.
//fragment、provide都是绿色通道
interceptorService.doInterceptions(postcard, new InterceptorCallback() {
/**

  • Continue process
  • @param postcard route meta
    */
    @Override
    public void onContinue(Postcard postcard) {
    _navigation(postcard, requestCode, callback);
    }

/**

  • Interrupt process, pipeline will be destory when this method called.
  • @param exception Reson of interrupt.
    */
    @Override
    public void onInterrupt(Throwable exception) {
    if (null != callback) {
    callback.onInterrupt(postcard);
    }

logger.info(Consts.TAG, "Navigation failed, termination by interceptor : " + exception.getMessage());
}
});
} else {
return _navigation(postcard, requestCode, callback);
}

return null;
}

private Object _navigation(final Postcard postcard, final int requestCode, final NavigationCallback callback) {
final Context currentContext = postcard.getContext();

switch (postcard.getType()) {
case ACTIVITY:
// 和我们平时用Intetn打开Activity一样
// Build intent
final Intent intent = new Intent(currentContext, postcard.getDestination());
intent.putExtras(postcard.getExtras()); // 额外的参数

// Set flags.
int flags = postcard.getFlags();
if (0 != flags) {
intent.setFlags(flags);
}

// Non activity, need FLAG_ACTIVITY_NEW_TASK
if (!(currentContext instanceof Activity)) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}

// Set Actions
String action = postcard.getAction();
if (!TextUtils.isEmpty(action)) {
intent.setAction(action);
}

// Navigation in main looper.
runInMainThread(new Runnable() {
@Override
public void run() {
startActivity(requestCode, currentContext, intent, postcard, callback);
}
});

break;
case PROVIDER:
return postcard.getProvider();// 如果是provide,之间返回
case BOARDCAST:
case CONTENT_PROVIDER:
case FRAGMENT:
Class<?> fragmentMeta = postcard.getDestination();
try {
Object instance = fragmentMeta.getConstructor().newInstance();
if (instance instanceof Fragment) {
((Fragment) instance).setArguments(postcard.getExtras());
} else if (instance instanceof android.support.v4.app.Fragment) {
((android.support.v4.app.Fragment) instance).setArguments(postcard.getExtras());
}

return instance;
} catch (Exception ex) {
logger.error(Consts.TAG, "Fetch fragment instance error, " + TextUtils.formatStackTrace(ex.getStackTrace()));
}
case METHOD:
case SERVICE:
default:
return null;
}

return null;
}

InterceptorService

@Route(path = “/arouter/service/interceptor”)
public class InterceptorServiceImpl implements InterceptorService

先到子线程中初始化,按照顺序执行我们定义的拦截器,因为拦截方法中可能有耗时操作,引起ANR,所以放在子线程中执行拦截操作。

@Override
public void init(final Context context) {
LogisticsCenter.executor.execute(new Runnable() {
@Override
public void run() {
if (MapUtils.isNotEmpty(Warehouse.interceptorsIndex)) {
for (Map.Entry<Integer, Class<? extends IInterceptor>> entry : Warehouse.interceptorsIndex.entrySet()) {
Class<? extends IInterceptor> interceptorClass = entry.getValue();
try {
IInterceptor iInterceptor = interceptorClass.getConstructor().newInstance();
iInterceptor.init(context);
Warehouse.interceptors.add(iInterceptor);
} catch (Exception ex) {
throw new HandlerException(TAG + “ARouter init interceptor error! name = [” + interceptorClass.getName() + “], reason = [” + ex.getMessage() + “]”);
}
}

interceptorHasInit = true;

logger.info(TAG, “ARouter interceptors init over.”);

synchronized (interceptorInitLock) {
interceptorInitLock.notifyAll();
}
}
}
});
}

@Override
public void doInterceptions(final Postcard postcard, final InterceptorCallback callback) {
if (MapUtils.isNotEmpty(Warehouse.interceptorsIndex)) {

checkInterceptorsInitStatus();

if (!interceptorHasInit) {
callback.onInterrupt(new HandlerException(“Interceptors initialization takes too much time.”));
return;
}

LogisticsCenter.executor.execute(new Runnable() {
@Override
public void run() {
//
CancelableCountDownLatch interceptorCounter = new CancelableCountDownLatch(Warehouse.interceptors.size());
try {
_execute(0, interceptorCounter, postcard);
interceptorCounter.await(postcard.getTimeout(), TimeUnit.SECONDS);
if (interceptorCounter.getCount() > 0) { // Cancel the navigation this time, if it hasn’t return anythings.
callback.onInterrupt(new HandlerException(“The interceptor processing timed out.”));
} else if (null != postcard.getTag()) { // Maybe some exception in the tag.
callback.onInterrupt((Throwable) postcard.getTag());
} else {
callback.onContinue(postcard);
}
} catch (Exception e) {
callback.onInterrupt(e);
}
}
});
} else {
callback.onContinue(postcard);
}
}

private static void _execute(final int index, final CancelableCountDownLatch counter, final Postcard postcard) {
if (index < Warehouse.interceptors.size()) {
// 我们自定义的拦截器
IInterceptor iInterceptor = Warehouse.interceptors.get(index);
iInterceptor.process(postcard, new InterceptorCallback() {
@Override
public void onContinue(Postcard postcard) {
// Last interceptor excute over with no exception.
counter.countDown();
// 处理完成,交给下一个拦截器
_execute(index + 1, counter, postcard); // When counter is down, it will be execute continue ,but index bigger than interceptors size, then U know.
}

@Override
public void onInterrupt(Throwable exception) {
// Last interceptor execute over with fatal exception.

postcard.setTag(null == exception ? new HandlerException(“No message.”) : exception); // save the exception message for backup.
counter.cancel();
// Be attention, maybe the thread in callback has been changed,
// then the catch block(L207) will be invalid.
// The worst is the thread changed to main thread, then the app will be crash, if you throw this exception!
// if (!Looper.getMainLooper().equals(Looper.myLooper())) { // You shouldn’t throw the exception if the thread is main thread.
// throw new HandlerException(exception.getMessage());
// }
}
});
}
}

inject

依赖注入,经过 Autowired 注解的 类,会自动生成类似下面这样的类,先获取Test3Activity这个类名,利用这个类名追加 ` ARouter$$Autowired,会得到

Test3Activity ARouter$$Autowired 这个类,实例化这个对象,调用这个对象中的inject方法,参数就是 Test3Activity 对象。

image-20210513234722439.png

image-20210513234800196.png

调用inject会

public void inject(Object thiz) {
_ARouter.inject(thiz);
}

static void inject(Object thiz) {
AutowiredService autowiredService = ((AutowiredService) ARouter.getInstance().build(“/arouter/service/autowired”).navigation());
if (null != autowiredService) {
autowiredService.autowire(thiz);
}
}

@Route(path = “/arouter/service/autowired”)
public class AutowiredServiceImpl implements AutowiredService {
private LruCache<String, ISyringe> classCache;
private List blackList;

@Override
public void init(Context context) {
classCache = new LruCache<>(50);
blackList = new ArrayList<>();
}

@Override
public void autowire(Object instance) {
doInject(instance, null);
}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

总结:

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

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

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

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

0)]

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

  • 8
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值