Android 组件化中使用动态创建的作用是解耦;
1. 反射机制
反射有两个作用:1.反编译:.class->.java;2.通过反射机制访问java对象中的属性,方法,构造器等;
实现反射,实际上是得到Class对象
data class Person(val name: String = "") {
private var age = -1
fun setAge(age: Int) {
this.age = age
}
override fun toString(): String {
return "Person(name='$name', age=$age)"
}
companion object {
fun getAuthor() {
LjyLogUtil.d("JinYang")
}
}
}
private fun initClass() {
//常用类
// import java.lang.Class //类的创建
// import java.lang.reflect.Constructor //反射类中构造方法
// import java.lang.reflect.Field//反射属性
// import java.lang.reflect.Method//反射方法
// import java.lang.reflect.Modifier//访问修饰符的信息
// 反射机制获取类:使用Class
//三种获取Class对象的方法
//1.会让ClassLoader装载类,并进行类的初始化
val c1 = Class.forName("com.ljy.publicdemo.activity.Person")
//2.会让ClassLoader装载类,不进行类的初始化操作
val c2 = Person::class.java
//3.在实例中获取,返回类对象运行时真正所指的对象
val c3 = Person("bob").javaClass
//无参数创建对象
val person = c1.newInstance() as Person
LjyLogUtil.d(person.toString())
//new Person()是直接创建一个实列,同时完成类的装载和连接
//newInstance是使用类加载机制,可以灵活的创建类的实例,更换类的时候无需修改之前的代码
//有参数的创建对象: 使用Constructor
val constructor = c1.getConstructor(String::class.java)
val person2 = constructor.newInstance("Emily") as Person
LjyLogUtil.d(person2.toString())
//反射类的属性:使用Field
val fieldAge = c1.getDeclaredField("age")
val fieldName = c1.getDeclaredField("name")
//取消封装,特别是取消私有字段的访问限制, 并不是将方法的权限设置为public,
//而是取消java的权限控制检查,
// 所以即使是public方法,其isAccessible默认也是false
fieldAge.isAccessible = true
fieldName.isAccessible = true
fieldAge.set(person2, 18)
LjyLogUtil.d("fieldAge.name=${fieldAge.name}")
//修改属性中的修饰符,使用Modifier
val modifierAge = Modifier.toString(fieldAge.modifiers)
val modifierName = Modifier.toString(fieldName.modifiers)
LjyLogUtil.d("modifierAge=$modifierAge, modifierName=$modifierName")
LjyLogUtil.d(person2.toString())
//反射类中的方法:使用Method
val method = c1.getDeclaredMethod("setAge", Int::class.java)//获取类中的方法
method.invoke(person2, 22)//通过反射调用方法
LjyLogUtil.d(person2.toString())
//遍历属性
for (it in c1.declaredFields) {
LjyLogUtil.d("declaredFields.it:${it.name}")
}
//遍历方法
for (it in c1.declaredMethods) {
LjyLogUtil.d("declaredMethods.it:${it.name}")
}
//遍历构造器
for (it in c1.declaredConstructors) {
LjyLogUtil.d("declaredConstructors.it:")
for (i in it.parameterTypes) {
LjyLogUtil.d("it.parameterTypes.i:${i.name}")
}
}
//反射静态方法
val clz = Class.forName("com.ljy.publicdemo.util.LjyLogUtil")
val m = clz.getDeclaredMethod("d", CharSequence::class.java)
m.invoke(LjyLogUtil::class.java, "log.d")
//反射泛型参数方法
//class Test {
// public void test(T t){
// LjyLogUtil.d("Test.test(),t:"+t);
// }
//}
val clz2 = Class.forName("com.ljy.publicdemo.activity.Test")
//注意这里有个泛型的基础--泛型擦除,编译器会自动类型向上转型,
//T向上转型是Object,所以下面第二个参数是Object.class
val tm = clz2.getDeclaredMethod("test", Object::class.java)
tm.isAccessible = true
tm.invoke(Test(), 666)
//Proxy动态代理机制
//java的反射机制提供了动态代理模式实现,代理模式的作用是
//为其他对象提供一种代理,以控制对这个对象的访问
//
// * 声明共同的接口
//public interface Subject {
// void doSomething();
//}
// * 具体实现类
//public class RealSubject implements Subject{
// @Override
// public void doSomething() {
// LjyLogUtil.d("RealSubject.doSomething()");
// }
//}
// * 代理类
//public class ProxyHandler implements InvocationHandler {
// private Object realSubject;
//
// public ProxyHandler(Object realSubject) {
// this.realSubject = realSubject;
// }
//
// @Override
// public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// //...可执行一些实际的业务逻辑
// Object result=method.invoke(realSubject, args);
// //...可执行一些实际的业务逻辑
// return result;
// }
//}
val real = RealSubject()
val proxySubject = Proxy.newProxyInstance(
Subject::class.java.classLoader,
arrayOf(Subject::class.java),
ProxyHandler(real)
) as Subject
proxySubject.doSomething()
//反射简化: jOOR
//当预期工程非常多的使用到反射时,我们需要更加简化的工具来优化开发流程,
//一个很棒的反射框架jOOR,非常轻量,让代码更加优雅
//项目地址 https://github.com/jOOQ/jOOR
//gradle中添加依赖
//implementation 'org.jooq:joor:0.9.13'
val helloStr: String? = Reflect.onClass("java.lang.String")//类似于Class.forName
.create("Hello jOOR")//调用类中构造方法
.call("substring", 8)//调用类中方法
.call("toString")
.get()//获取包装好的对象
LjyLogUtil.d("helloStr=$helloStr")
//也支持动态代理
Reflect.onClass(RealSubject::class.java)
.create()
.`as`(Subject::class.java)
.doSomething()
}
}
2. 动态创建fragment
- 开发中经常会用到activity+多fragment的场景;
- 正常使用activity引用fragment方式时是强引用(import包名),在组件化项目中,如果fragment是组件module中的,
activity是主module或其他module的, 就会造成耦合严重,当需要移除时也很麻烦,那么如何降低耦合呢, 这就可以通过上面说的反射实现;
//管理fragment标题及路径的类
public class PageConfig {
public static List pageTitles = new ArrayList();
public static List getPageTitles(Context context) {
pageTitles.clear();
pageTitles.add("Fragment1");
pageTitles.add("Fragment2");
pageTitles.add("Fragment3");
return pageTitles;
}
private static final String PATH_FRAGMENT1 = "com.ljy.publicdemo.activity.fragment.Fragment1";
private static final String PATH_FRAGMENT2 = "com.ljy.publicdemo.activity.fragment.Fragment2";
private static final String PATH_FRAGMENT3 = "com.ljy.publicdemo.activity.fragment.Fragment3";
public static String[] fragmentNames = {
PATH_FRAGMENT1,
PATH_FRAGMENT2,
PATH_FRAGMENT3,
};
}
//通过反射遍历添加
class FragmentActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_frag)
try {
//遍历Fragment地址
for (address in PageConfig.fragmentNames) {
//反射获得Class
val clazz = Class.forName(address)
//创建类
val fragment = clazz.newInstance() as Fragment
//添加到viewPagerAdapter的资源
supportFragmentManager
.beginTransaction()
.add(R.id.frame_layout, fragment)
.commit()
}
} catch (e: ClassNotFoundException) {
} catch (e: IllegalAccessException) {
} catch (e: InstantiationException) {
}
}
}
使用反射会相对安全,也会降低耦合,但反射会造成一定的效率下降;
ARouter也提供了跨模块获取fragment对象的操作
class FragmentActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_frag)
//ARouter提供了跨模块获取fragment对象的操作
val fragment1=ARouter.getInstance()
.build(ARouterPath.FRAGMENT_PATH_1)
.navigation() as Fragment1
fragment1.fragmentManager = supportFragmentManager
supportFragmentManager
.beginTransaction()
.add(R.id.frame_layout, fragment1)
.commit()
}
}
底层_ARouter类中也是通过反射实现
private Object _navigation(final Context context, final Postcard postcard,
final int requestCode, final NavigationCallback callback) {
final Context currentContext = null == context ? mContext : context;
switch (postcard.getType()) {
...
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()));
}
...
}
return null;
}
- 使用跨模块获取Fragment非日常适合在单Activity+多fragment的app架构中使用,因为fragment划分模块作为入口的设计,使用ARouter的方式非常适应模块间解耦的要求;
- 当业务模块选用fragment的形式作为业务入口时,需要充分考虑模块间业务跳转的解耦性,以保证业务分离后不会造成app崩溃
3. 动态配置Application
- 开发中我们经常会遇到某些功能模块中需要一些初始化的操作,只能强引用到主module的application中,这种情况如何更好的解耦呢?
//1. 通过主module的application获取各module的初始化文件,
// 然后通过反射初始化的java文件来调用初始化方法
/**
* @Author: LiuJinYang
* 在base module中定义通用接口
*/
public interface BaseAppInit {
/**
* 需要优先被初始化的
*/
boolean onInitSpeed(Application application);
/**
* 可以延迟初始化的
*/
boolean onInitLow(Application application);
}
/**
* @Author: LiuJinYang
*
* 在组件module中的实现
*/
public class LibAppInitImpl implements BaseAppInit {
@Override
public boolean onInitSpeed(Application application) {
//一些初始化操作
return false;
}
@Override
public boolean onInitLow(Application application) {
//一些初始化操作
return false;
}
}
//主module中配置文件
public class PageConfig {
private static final String LIB_APP_INIT="com.jinyang.mylibrary.LibAppInitImpl";
public static String[] initModules={LIB_APP_INIT,};
}
//主application中通过反射加载组件module的初始化文件
public class DemoApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
initModulesSpeed();
//todo 。。。其他的初始化操作
initModulesLow();
}
private void initModulesSpeed() {
for (String address : PageConfig.initModules) {
try {
//反射获得Class
Class clazz = Class.forName(address);
BaseAppInit moduleInit = (BaseAppInit) clazz.newInstance();
moduleInit.onInitSpeed(this);
} catch (ClassNotFoundException
| IllegalAccessException | InstantiationException e) {
//todo ...
}
}
}
private void initModulesLow() {
for (String address : PageConfig.initModules) {
try {
//反射获得Class
Class clazz = Class.forName(address);
BaseAppInit moduleInit = (BaseAppInit) clazz.newInstance();
moduleInit.onInitLow(this);
} catch (ClassNotFoundException
| IllegalAccessException | InstantiationException e) {
//todo ...
}
}
}
}
上面代码可以基本满足组件化中的解耦,但反射有一定的性能损耗,对于追求app秒开体验的需求,
可以通过RxJava使用非UI线程初始化各组件module;
2. 通过主module的application中继承base module的application实现
/**
* @Author: LiuJinYang
*
* baseModule中声明一个初始化类
*/
class BaseAppLogic {
protected BaseApplication mApplication;
public BaseAppLogic() {
}
public void setApplication(@NonNull BaseApplication application) {
this.mApplication = application;
}
public void onCreate(){}
public void onTerminate(){}
public void onLowMemory(){}
public void onTrimMemory(int level){}
public void onConfigurationChanged(Configuration configuration){}
}
/**
* @Author: LiuJinYang
* base module的application中做初始化文件的启动封装
*/
public abstract class BaseApplication extends Application {
private List> logicClassList =new ArrayList<>();
private ListlogicList=new ArrayList<>();
@Override
public void onCreate() {
super.onCreate();
initLogic();
logicCreate();
for (BaseAppLogic logic:logicList){
logic.onCreate();
}
}
/**
* 主module的application中调用
*/
protected abstract void initLogic();
protected void registerApplicationLogic(String logicClassPath){
Class extends BaseAppLogic> logicClass= null;
try {
logicClass = (Class extends BaseAppLogic>) Class.forName(logicClassPath);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
logicClassList.add(logicClass);
}
protected void logicCreate(){
for(Class<?extends BaseAppLogic> logicClass:logicClassList){
try {
BaseAppLogic appLogic=logicClass.newInstance();
logicList.add(appLogic);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
@Override
public void onTerminate() {
super.onTerminate();
for (BaseAppLogic logic:logicList){
logic.onTerminate();//其他BaseAppLogic接口同样处理
}
}
}
/**
* @Author: LiuJinYang
* 每个组件module中需要初始化时继承此类,然后复写需要的接口
*/
public class LibInitLogic extends BaseAppLogic{
@Override
public void onCreate() {
super.onCreate();
Log.d("LJY_LOG","LibInitLogic.onCreate");
}
}
//主module的application继承BaseApplication,调用initLogic注册所有BaseAppLogic的实现类
public class MyApplication extends BaseApplication {
@Override
protected void initLogic() {
registerApplicationLogic("com.jinyang.mylibrary.LibInitLogic");
}
}
阅读全文
下载说明:
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.dandroid.cn/19692,转载请注明出处。
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.dandroid.cn/19692,转载请注明出处。
评论0