打造自己的一套IOC注解框架

189 阅读2分钟

IOC,控制反转(Inversion of Control,英文缩写为IOC),其实就是反射加注解。

使用:

public class MainActivity extends AppCompatActivity {

    @ViewById(R.id.tv_personally)
    private TextView tv_personally;

    private int count = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ViewUtils.inject(this);
        tv_personally.setText("Hi IOC");
    }


    @OnClick({R.id.iv_personally, R.id.tv_personally})
    @CheckNet  // 检测网络
    private void onClick(View view) {
        switch (view.getId()) {
            case R.id.iv_personally:
                Toast.makeText(MainActivity.this, "点击了图片", Toast.LENGTH_LONG).show();
                break;
            case R.id.tv_personally:
                count++;
                tv_personally.setText(count + "");
                break;
        }
    }
}

View属性注入

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ViewById {
    int value();
}
/**
 * View 的 findViewById的辅助类
 */
public class ViewFinder {
    private Activity mActivity;
    private View mView;

    public ViewFinder(Activity activity) {
        this.mActivity = activity;
    }

    public ViewFinder(View view) {
        this.mView = view;
    }

    public View findViewById(int viewId) {
        return mActivity != null ? mActivity.findViewById(viewId) : mView.findViewById(viewId);
    }
public class ViewUtils {
    public static void inject(Activity activity) {
        inject(new ViewFinder(activity), activity);
    }

    public static void inject(View view) {
        inject(new ViewFinder(view), view);
    }

    public static void inject(View view, Object object) {
        inject(new ViewFinder(view), object);
    }

    //兼容上面三个方法 object:反射需要执行的类
    private static void inject(ViewFinder finder, Object object) { 
        injectFiled(finder, object);
        injectEvent(finder, object);
    }

    /**
     * 注入View属性
     */
    private static void injectFiled(ViewFinder finder, Object object) {
        //1、获取类里面所有的属性
        Class<?> clazz = object.getClass();
        //获取所有属性包括私有和共有
        Field[] fields = clazz.getDeclaredFields();
        //2、获取ViewById里面的value值
        for (Field field : fields) {
            ViewById viewById = field.getAnnotation(ViewById.class);
            if (viewById != null) {
                //获取注解里面的id值  : R.id.tv_personally
                int viewId = viewById.value();
                //3、findViewById找到View
                View view = finder.findViewById(viewId);
                if (view != null) {
                    //能够注入所有的修饰符 包括private
                    field.setAccessible(true);
                    try {
                        //4、动态的注入找到的View(可以理解为给属性赋值)
                        field.set(object, view);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

    }
}

点击事件注入

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OnClick {
    int[] value();
}
/**
 * 点击事件注入
 */
private static void injectEvent(ViewFinder finder, Object object) {
    //1、获取类里面所有的方法
    Class<?> clazz = object.getClass();
    //获取所有方法包括私有和共有
    Method[] methods = clazz.getDeclaredMethods();
    // 2.获取方法上面的所有id
    for (Method method : methods) {
        OnClick onClick = method.getAnnotation(OnClick.class);
        if (onClick != null) {
            int[] viewIds = onClick.value();
            if (viewIds.length > 0) {
                for (int viewId : viewIds) {
                    // 3.遍历所有的id 先findViewById然后 setOnClickListener
                    View view = finder.findViewById(viewId);
                    if (view != null) {
                        view.setOnClickListener(new DeclaredOnClickListener(method, object));
                    }
                }
            }
        }
    }
}

private static class DeclaredOnClickListener implements View.OnClickListener {
    private Method mMethod;
    private Object mHandlerType;

    public DeclaredOnClickListener(Method method, Object handlerType) {
        mMethod = method;
        mHandlerType = handlerType;
    }

    @Override
    public void onClick(View v) {
        mMethod.setAccessible(true);
        try {
            // 4.反射执行方法
            mMethod.invoke(mHandlerType, v);
        } catch (Exception e) {
            e.printStackTrace();
            try {
                mMethod.invoke(mHandlerType, null);
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        }
    }
}

扩展动态检测网络注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckNet {

}
private static class DeclaredOnClickListener implements View.OnClickListener {
    private Method mMethod;
    private Object mHandlerType;

    public DeclaredOnClickListener(Method method, Object handlerType) {
        mMethod = method;
        mHandlerType = handlerType;
    }

    @Override
    public void onClick(View v) {
        //新增此处
        CheckNet checkNet = mMethod.getAnnotation(CheckNet.class);
        if (checkNet!=null){
            if (!isNetworkAvailable(v.getContext())){
                Toast.makeText(v.getContext(), "没有网络呦", Toast.LENGTH_LONG).show();
                return;
            }
        }
        mMethod.setAccessible(true);
        try {
            // 4.反射执行方法
            mMethod.invoke(mHandlerType, v);
        } catch (Exception e) {
            e.printStackTrace();
            try {
                mMethod.invoke(mHandlerType, null);
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        }
    }
}
/**
 * 检查当前网络是否可用
 */
private static boolean isNetworkAvailable(Context context) {
    // 获取手机所有连接管理对象(包括对wi-fi,net等连接的管理)
    ConnectivityManager connectivityManager = (ConnectivityManager)
            context.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (connectivityManager != null) {
        // 获取NetworkInfo对象
        NetworkInfo[] networkInfo = connectivityManager.getAllNetworkInfo();

        if (networkInfo != null && networkInfo.length > 0) {
            for (int i = 0; i < networkInfo.length; i++) {
                // 判断当前网络状态是否为连接状态
                if (networkInfo[i].getState() == NetworkInfo.State.CONNECTED) {
                    return true;
                }
            }
        }
    }
    return false;
}

最后别忘了加上网络检测权限:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

参考文章: www.jianshu.com/p/2570c2de0…