在Android中使用IOC框架让代码更清爽(一)

简介: 在Android中使用IOC框架让代码更清爽(一)

控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对角编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心。 控制反转一般分为两种类型,依赖注入(Dependency Injection,简称DI)和依赖查找(Dependency Lookup)。依赖注入应用比较广泛。


通俗点讲什么是IOC呢?


很久很久以前,我们创建某件物品都是用双手在流水线上创建的,当我们有了机器后,这个机器就替代了人,帮助人创造物品,这个过程倒置了反转。在Android中,你获取控件,都需要自己手动获取,那么反转过来顾名思义就是程序自动获取控件。


相信在系统学习过Java Web的Spring框架的人对IOC应该一点也不陌生,那你们知道在Android中怎么应用吗,这可能设及的知识有点多,包括反射,Java注解类,设计模式之代理模式等知识。下面我将演示怎么运行IOC来获取控件,设置回调方法的应用。


1.在Android中获取控件


我们知道,Android手机界面的所有布局都配置在资源文件XML中,如果想要获取某个布局,一般情况下,我们是使用如下方法获取的:


setContentView(R.layout.activity_main);


现在我们来颠覆你对这个的应用,下面来看看应用IOC框架是怎么获取这个应用的。


①首先我们创建我们的注解类ContentView。


在Android Studio的创建流程如下:


㈠点击包名创建类


23.png


㈡选中注解类并创建


24.png


㈢与一个方法,获取等下传进来的ID

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ContentView {
    int value();
}


@Target表示注解可以用于什么地方,这里用于类,其他参数如:FILED(成员),METHOD(方法),PACKAGE(包),ANNOTATION_TYPE(注解的注解),CONSTRUCTOR(构造函数),PARAMETER(参数),LOCAL_VARIABLE(局部变更)


@Retention什么时候加载注解类,一般都是RetentionPolicy.RUNTIME运行的时候。


②新建一个注入工具类InjectUtils.class:

public class InjectUtils {
    public static final String ACTIVITY_MAIN_CONTENTVIEW="setContentView";
    /**
     * 注入所有
     * @param activity
     */
    public static void injectAll(Activity activity){
        injectContentView(activity);
    }
    /**
     * 注入ContentView
     * @param activity
     */
    public static void injectContentView(Activity activity){
        Class<? extends Activity> clazz = activity.getClass();//获取该类信息
        ContentView contentView = clazz.getAnnotation(ContentView.class);//获取该类ContentView的注解
        //如果有注解
        if(contentView!=null){
            int viewId=contentView.value();//获取注解类参数
            try {
                Method method=clazz.getMethod(ACTIVITY_MAIN_CONTENTVIEW,int.class);//获取该方法的信息
                method.setAccessible(true);//获取该方法的访问权限
                method.invoke(activity,viewId);//调用该方法的,并设置该方法参数
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}


注解虽然详细,有可能不写点,有的人理解method.invoke有点困难。下面我来解释一下。


method.invoke(activity,viewId);你可能这样理解,activity调用了method设置了viewID,如果还不够形象,看方法下面:


setContentView.invoke(MainActivity.this,R.layout.activity_main)这样虽然不伦不类,但是你应该理解了,就是invoke的第一个参数调用method方法,该方法的参数就是invoke的第二个参数。


获取注解类的参数,如下代码中:

@ContentView(R.layout.activity_main)
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        InjectUtils.injectAll(MainActivity.this);
    }
}

@ContentView(R.layout.activity_main)中的R.layout.activity_main的值。然后用调用工具类调用设置其setContentView方法,这样布局文件就加载进来了。


运行后得到如下图所示:


25.png


2.用IOC加载控件


相信大家加载控件的方法,基本上都是千篇一律,如下所示:


this.but=(Button)findViewById(R.id.but);


假如现在有N个控件,估计你整个屏幕都被控件包围,写其他代码还需要滑动滚动条。这样是不是重复劳动是不是不值得?


下面我们来使用IOC框架来获取控件。


①创建注解类InjectControl,代码如下:


@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectControl {
    int value();
}


相信经过上面的介绍,这个很容易理解。


②在MainActivity配置注解类。


代码如下:

@InjectControl(value = R.id.content)
private TextView content;
@InjectControl(value = R.id.myBut1)
private Button myBut1;
@InjectControl(value = R.id.myBut2)
private Button myBut2;


③最后就是注入所有控件。


代码在InjectUtils中,如下:


public static final String ACTIVITY_MAIN_FINDVIEWBYID="findViewById";
/**
 *注入控件
 * @param activity
 */
public static void injectControl(Activity activity){
    Class<? extends Activity> clazz = activity.getClass();//获取该类信息
    Field[] fields=clazz.getDeclaredFields();//获致所有成员变更
    for (Field field:fields) {
        InjectControl injectControl = field.getAnnotation(InjectControl.class);
        if(injectControl!=null){
            int viewId=injectControl.value();
            try {
                Method method=clazz.getMethod(ACTIVITY_MAIN_FINDVIEWBYID, int.class);
                method.setAccessible(true);
                field.setAccessible(true);
                Object object=method.invoke(activity, viewId);
                field.set(activity,object);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}


这里几点需要解释一下,为什么用getDeclaredFields()获取成员变更,不用getFields(),因为getFields只能获取类中公有的成员变量,如果要获取包括私有的成员变量,就需要使用上面的方法,而我们定义的都是私有,故必须使用该方法,


这里调用了再次invoke的方法,一次是方法调用的,一次是成员变量调用的,为什么这样设计,因为,这里必须用二步才能完成。


我们就算直接调用findViewById也是两步,首先我们要调用this.findViewById()等到View后才赋值给某个变量,虽然看上去只有一条语句,但是却是两个部分。同理,我们必须调用activity.findViewById()方法获取到View后,才能把View赋值给field。所以这里有两步。


为了验证代码,我在MainActivity的onCreate()方法里面加入了如下代码:

if(myBut1!=null && myBut2!=null){
    Toast.makeText(this,"按钮已经获取到了",Toast.LENGTH_SHORT).show();
}

运行结果如下:


26.png


其他的上面的解释了,这里就不在叙述了。下面难点来了。

相关文章
|
4月前
|
物联网 区块链 vr&ar
未来已来:探索区块链、物联网与虚拟现实技术的融合与应用安卓与iOS开发中的跨平台框架选择
【8月更文挑战第30天】在科技的巨轮下,新技术不断涌现,引领着社会进步。本文将聚焦于当前最前沿的技术——区块链、物联网和虚拟现实,探讨它们各自的发展趋势及其在未来可能的应用场景。我们将从这些技术的基本定义出发,逐步深入到它们的相互作用和集成应用,最后展望它们如何共同塑造一个全新的数字生态系统。
|
1月前
|
算法 JavaScript Android开发
|
17天前
|
开发框架 Dart Android开发
安卓与iOS的跨平台开发:Flutter框架深度解析
在移动应用开发的海洋中,Flutter作为一艘灵活的帆船,正引领着开发者们驶向跨平台开发的新纪元。本文将揭开Flutter神秘的面纱,从其架构到核心特性,再到实际应用案例,我们将一同探索这个由谷歌打造的开源UI工具包如何让安卓与iOS应用开发变得更加高效而统一。你将看到,借助Flutter,打造精美、高性能的应用不再是难题,而是变成了一场创造性的旅程。
|
2月前
|
Java 程序员 API
Android|集成 slf4j + logback 作为日志框架
做个简单改造,统一 Android APP 和 Java 后端项目打印日志的体验。
116 1
|
2月前
|
安全 Java 网络安全
Android远程连接和登录FTPS服务代码(commons.net库)
Android远程连接和登录FTPS服务代码(commons.net库)
29 1
|
2月前
|
Android开发 Swift iOS开发
探索安卓与iOS开发的差异:从代码到用户体验
【10月更文挑战第5天】在移动应用开发的广阔天地中,安卓和iOS两大平台各占半壁江山。它们在技术架构、开发环境及用户体验上有着根本的不同。本文通过比较这两种平台的开发过程,揭示背后的设计理念和技术选择如何影响最终产品。我们将深入探讨各自平台的代码示例,理解开发者面临的挑战,以及这些差异如何塑造用户的日常体验。
|
3月前
|
存储 Java Android开发
🔥Android开发大神揭秘:从菜鸟到高手,你的代码为何总是慢人一步?💻
在Android开发中,每位开发者都渴望应用响应迅速、体验流畅。然而,代码执行缓慢却是常见问题。本文将跟随一位大神的脚步,剖析三大典型案例:主线程阻塞导致卡顿、内存泄漏引发性能下降及不合理布局引起的渲染问题,并提供优化方案。通过学习这些技巧,你将能够显著提升应用性能,从新手蜕变为高手。
33 2
|
3月前
|
前端开发 Java 数据库
💡Android开发者必看!掌握这5大框架,轻松打造爆款应用不是梦!🏆
在Android开发领域,框架犹如指路明灯,助力开发者加速应用开发并提升品质。本文将介绍五大必备框架:Retrofit简化网络请求,Room优化数据库访问,MVVM架构提高代码可维护性,Dagger 2管理依赖注入,Jetpack Compose革新UI开发。掌握这些框架,助你在竞争激烈的市场中脱颖而出,打造爆款应用。
399 3
|
3月前
|
编译器 Android开发 开发者
带你了解Android Jetpack库中的依赖注入框架:Hilt
本文介绍了Hilt,这是Google为Android开发的依赖注入框架,基于Dagger构建,旨在简化依赖注入过程。Hilt通过自动化的组件和注解减少了DI的样板代码,提高了应用的可测试性和可维护性。文章详细讲解了Hilt的主要概念、基本用法及原理,帮助开发者更好地理解和应用Hilt。
88 8
|
4月前
|
设计模式 Java Android开发
探索安卓应用开发:从新手到专家的旅程探索iOS开发中的SwiftUI框架
【8月更文挑战第29天】本文旨在通过一个易于理解的旅程比喻,带领读者深入探讨安卓应用开发的各个方面。我们将从基础概念入手,逐步过渡到高级技术,最后讨论如何维护和推广你的应用。无论你是编程新手还是有经验的开发者,这篇文章都将为你提供有价值的见解和实用的代码示例。让我们一起开始这段激动人心的旅程吧!