首页 文章 精选 留言 我的

精选列表

搜索[DUOX技术],共10007篇文章
优秀的个人博客,低调大师

Android技术分享| Context浅析

类继承图 我们来看下关于 Context 的类继承图,我们通过查看源码得知,Context 是一个抽象类,所以它肯定有其实现类,查阅得知它的实现类为 ContextWrapper 和 ContextImpl ,所以它的继承图如下: 以上的 Context 类继承关系清晰简洁,可以得知,Application 、 Service 、Activity 都是继承的 Context 类,所以从这里我们可以得知: Context 数量 = Activity 数量 + Service 数量 + 1 另外,我们可以看到 Application 和 Service 都是直接继承 ContextWrapper 的而 Activity 却是继承 ContextThemeWrapper 的,这是为何?其实 ContextThemeWrapper 是关于主题类的,Activity 是有界面的,而 Application 和 Service 却没有。接下来我们来详细看下它们的源码实现。 ContextWrapper 我们进入到 ContextWrapper 源码中可以发现,它其实调用了 mBase 里面的方法,而 mBase 其实是 ContextImpl ,所以最终还是得调用它的实现类 ContextImpl 类里面的方法。 public class ContextWrapper extends Context { Context mBase; public ContextWrapper(Context base) { mBase = base; } protected void attachBaseContext(Context base) { if (mBase != null) { throw new IllegalStateException("Base context already set"); } mBase = base; } //其余的都是覆盖Context里面的方法 } 我们可以按照上面的类的继承图进行依次分析,由上面可以知道 ContextWrapper 其实是调用 ContextImpl 里面的方法,所以 Application 和 Service 还有 Activity 它们应该都跟 ContextImpl 有关的。到底是不是这样的呢?我们追踪源码进行分析。 Application 类似于 Java 的 main 启动方法程序,Android 也有一个类似的方法,那就是在 ActivityThread 类中也有一个 main ,这是开始的地方,我们从这里进行一点一点跟踪: ActivityThread#main //省略部分代码... Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); //省略部分代码... Looper.loop(); //省略部分代码... 我们找到 ActivityThread 的 main 方法,省略无关代码,这个 main 方法就是不断的从消息队列中获取消息,然后进行处理。我们本次不分析 Looper 相关的东西,只分析跟 Context 有关的内容,继续进入 attach 方法, Android 分析源码,不能一头扎进去,我们应该主要分析它的流程。 ActivityThread#attach //省略部分代码... mInstrumentation = new Instrumentation(); ContextImpl context = ContextImpl.createAppContext( this, getSystemContext().mPackageInfo); //Application的实例创建 mInitialApplication = context.mPackageInfo.makeApplication(true, null); //调用Application里面的生命周期方法onCreate mInitialApplication.onCreate(); //省略部分代码... 这里面出现了 ContextImpl ,所以下面应该会跟 Application 扯上关系,所以进入到 makeApplication 方法中继续往下追踪, LoadedApk#makeApplication //省略部分代码... Application app = null; ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); app = mActivityThread.mInstrumentation.newApplication( cl, appClass, appContext); appContext.setOuterContext(app); //省略部分代码... 最终又进入到 Instrumentation#newApplication 方法里面 Instrumentation#newApplication static public Application newApplication(Class<?> clazz, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException { Application app = (Application)clazz.newInstance(); app.attach(context); return app; } Application#attach /** * @hide */ /* package */ final void attach(Context context) { attachBaseContext(context); mLoadedApk = ContextImpl.getImpl(context).mPackageInfo; } 走到这里就很明清晰了,最终将会调用 ContextWrapper 的 attachBaseContext 方法。从上面到这里,如预料的一样,分析到这里,记住了多少?是不是只知道 Application 里面最终会调用 attachBaseContext 这个方法?这样的话就对了,不能一头扎进代码的海洋里,到处遨游,那样会迷失方向的,Android 源码那么大,那么多,一一细节分析根本是不大可能的,所以只能把握流程,然后再针对性的分析实现过程。接着分析 Service 里面相关的方法。 Service 对于 Service ,我们在 ActivityThread 中可以发现有个方法叫 handleCreateService ,这里面有关于 Service 和 ContextImpl 之间的联系。 ActivityThread#handleCreateService Service service = null; ContextImpl context = ContextImpl.createAppContext(this, packageInfo); context.setOuterContext(service); Application app = packageInfo.makeApplication(false, mInstrumentation); service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService()); service.onCreate(); 对于 Application 的那段代码我们可以发现,这两者及其类似,我们进入到 attach 方法中查看相关代码,发现 /** * @hide */ public final void attach( Context context, ActivityThread thread, String className, IBinder token, Application application, Object activityManager) { //调用attachBaseContext方法 attachBaseContext(context); mThread = thread; // NOTE: unused - remove? mClassName = className; mToken = token; mApplication = application; mActivityManager = (IActivityManager)activityManager; mStartCompatibility = getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.ECLAIR; } 代码很简单,就是这样跟 ContextImpl 扯上关系的。因为 Service 和 Application 都是继承的 ContextWrapper 类,接下来我们来分析一下关于 Activity 的代码。 Activity 在这里说明一下为什么 Service 和 Application 都是继承的 ContextWrapper 类而 Activity 却是继承 ContextThemeWrapper 那是因为 Activity 是带有界面显示的,而 Service 和 Application 却没有,所以从名字我们可以看到 ContextThemeWrapper 包含主题的信息,同时 ContextThemeWrapper 却又是继承自 ContextWrapper ,分析 ContextThemeWrapper 源码我们可以看到,里面基本都是关于 theme 的方法,同时它也覆盖了 attachBaseContext 方法。 我们进入 Activity 源码也发现它也有和 Service 类似的 attach 方法 final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, Configuration config, String referrer, IVoiceInteractor voiceInteractor, Window window, ActivityConfigCallback activityConfigCallback) { //省略部分代码... attachBaseContext(context); 接下来我们来分析一下 Activity 在哪里和这个扯上关系的。 ActivityThread#performLaunchActivity performLaunchActivity 这个方法其实就是启动 Activity 的方法 ,我们以后再来学习关于这个方法的内容,现在先分析 Context 的内容。我们进入到这个方法查看: //省略部分代码... ContextImpl appContext = createBaseContextForActivity(r); Activity activity = null; //省略部分代码... activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.referrer, r.voiceInteractor, window, r.configCallback); //省略部分代码... 首先通过 createBaseContextForActivity 方法创建ContextImpl 然后直接有 Activity attach 进去。到此为止,关于 Application 、Service 和 Activity 关于Context 的源码基本就差不多了。接下来我们来解决一些实际的内容。 实例理解 既然 Application、Service 和 Activity 都有 Context 那么它们之间到底有啥区别呢?同时 getApplicationContext 和 getApplication() 又有什么区别呢?接下来我们通过代码进行验证。 我们现在的项目一般都有自定义 Application 的类进行一些初始化操作,本例中也新建一个 MyApplication 的类继承自 Application,然后在Manifest.xml中进行注册,代码如下: public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); Log.d("androidos_analysis", "getApplicationContext()——> " + getApplicationContext()); Log.d("androidos_analysis", "getBaseContext() ——> " + getBaseContext()); } } 打印结果如下: getApplicationContext()——> com.ihidea.androidosanalysis.MyApp@9831cf9 getBaseContext() ——> android.app.ContextImpl@13d643e 我们发现当我们通过 getApplicationContext 获取的是我们申明的 Application 实例,而通过 getBaseContext 获取到的却是 ContextImpl 这是为什么呢?我们查看它们的实现发现 ContextWrapper#getBaseContext /** * @return the base context as set by the constructor or setBaseContext */ public Context getBaseContext() { return mBase; } 其实在上文我们已经分析过了它们的源码,我们知道其实这个mBase就是 ContextImpl 了。而 getApplicationContext ContextWrapper#getApplicationContext @Override public Context getApplicationContext() { return mBase.getApplicationContext(); } 通过上面分析我们知道 其实 Application 它本身也是一个 Context 所以,这个们返回的就是它自己了。所以这里获取getApplicationContext()得到的结果就是MyApplication本身的实例。 有时候我们代码里面也会有关于 getApplication 的用法,那么 这个跟 getApplicationContext 又有什么区别呢?我们再来log一下就知道了。 我们创建一个 MainActivity 然后在里面打印两行代码: MainActivity#onCreate Log.d("androidos_analysis", "getApplicationContext()——> " + getApplicationContext()); Log.d("androidos_analysis", "getApplication() ——> " + getApplication()); 我们可以发现 这两个返回的结果都是 一样的,其实不难理解, Activity#getApplication /** Return the application that owns this activity. */ public final Application getApplication() { return mApplication; } 其实 getApplication 返回的就是 Application 所以这两者是一样的了。但是都是返回的 Application ,Android 为什么要存在这两个方法呢?这就涉及到作用域的问题了,我们可以发现使用 getApplication 的方法的作用范围是 Activity 和 Service ,但是我们在其他地方却不能使用这个方法,这种情况下我们就可以使用 getApplicationContext 来获取 Application 了。什么情况下呢?譬如:BroadcastReceiver 我们想在Receiver 中获取 Application 的实例我们就可以通过这种方式来获取: public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { MyApplication myApp = (MyApplication) context.getApplicationContext(); //... } }

优秀的个人博客,低调大师

AnalyticDB for MySQL技术架构解析

企业数据需求不断变化,近年来变化趋势日益明显,从数据的3V特性看:体积,速度和变化;Big Data强调数据量,PB级以上,是静态数据。而Fast Data在数据量的基础上,意味着速度和和变化,意味着客户可以更加实时化、更加快速地进行数据处理。 在Forrester最近的一项研究中,超过75%的受访公司已经使用Fast Data解决方案。 在接受调查的人中,88%表示他们需要近乎实时地对数据执行分析。 AnalyticDB是阿里巴巴自主研发、唯一经过超大规模以及核心业务验证的PB级实时数据仓库,是FastData的最佳代表。自2012年第一次在集团发布上线以来,至今已累计迭代发布近百个版本,支撑起集团内的电商、广告、菜鸟、文娱、飞猪等众多在线分析业务。AnalyticDB于2014年在阿里云开始正式对外输出,支撑行业既包括传统的大中型

优秀的个人博客,低调大师

Redis缓存技术的应用?

Redis是一款免费开源的遵守BSD协议,是高性能的NOsql 缓存 Key-value数据库。Redis支持数据持久化,可以在将内存中的数据保持在词牌当中,重启后还可以再次加载进行使用,Redis支持简单的Key-valus类型数据,同时还提供了list set zset hash等数据结构的存储,同时还支持数据备份,即主从复制。Redis的经典应用场景:1.缓存热点数据:热点数据(经常会被查询,但不是进场被修改或者删除的数据),首选是使用redis缓存,redis的性能非常优越。2.计数器:诸如统计点击数,访问数,点赞数,评论数,浏览数等应用,由于单线程,避免了并发问题,保证数据的正确性,并且100%毫秒级性能,同时开启Redis持久化,以便于持久化数据。3.单线程机制:验证前段的重复请求,可以自由扩展类似情况。可以通过red

优秀的个人博客,低调大师

内网穿透技术浅评

科普一下给有需要的童鞋参考。穿透原理大致分如下几类: 1、代理穿透 原理示意图: 优势: 保持100%穿透成功率 用户无需公网IP 不足: 运营方提供公网访问入口,硬件投入大 带宽要求高,免费用户往往会被限速,产生免费使用上的“鸡肋” 2、直接穿透 原理示意图: 优势: 自主可控,无需第三方转发 保持100%穿透成功率 不足: 服务端必须具备公网IP 带宽取决于服务端和客户端两者的最小带宽(面向云主机带宽不友好,主要是贵!死贵!!) 由于直接暴露在公网,会有安全问题 需要自己搭建,门槛较高 3、P2P穿透 原理示意图: 优势: 点对点,能最大化使用带宽,使用感知友好 不足: Ipv4环境下成功率取决于NAT类型,移动网络(3G/4G下)基本没戏 Ipv6环境下成功率高,取决于防火墙策略(防火墙穿透) 几乎全基于UDP协议或其衍生自定义协议,安全性和可靠性或多或少存在缺陷 4、Ssh隧道穿透: 略 常用免费工具穿透姿势: -/- 代理穿透 直接穿透 P2P穿透 自主代理 公网IP 备注 花生壳 YES NO NO NO 不需要 限速到怀疑人生 teamviewer YES NO NO NO 不需要 烦人的商用提示 Ngrok YES YES NO YES 需要 Frp YES YES YES/UDP YES 需要 三种方式选其一 smarGate YES YES YES/TCP YES 不需要 同时支持,P2P优先 附:Frp:https://github.com/fatedier/frpNgrok:https://github.com/inconshreveable/ngroksmarGate: https://github.com/lazy-luo/smarGate

优秀的个人博客,低调大师

Cassandra技术介绍之开篇

Cassandra是一款分布式的去中心化的数据库,她脱胎于Dynamo以及bigtable,吸收了二者的架构以及数据模型在开源社区的孵化下达到今天这么一个程度。CAP理论中她更强调AP两点,当然C的属性也是可调的,C 和A 这2块在Cassandra身上可以看到一个权衡的存在。本文会从以下几个方面去介绍Cassandra相关知识: 基本架构 部署运维 使用方法 一:基本架构 Cassandra可以有多dc的部署方案,且也有适合在云环境下的部署方案,从复杂的snitch到simple的snitch。不同的环境有不同的部署方式,如果你希望你的cluster下面都是在一个dc,可以使用simple snitch,如果想要有更复杂的rack 以及dc方案,配合network的拓扑,可以组合成比较合适的一套多dc的架构。当然也有适合云上很亲和性的sn

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册