文章纯属个人学习的代码实现
网易云微专业公开课上面利用反射实现了类似
ButterKnife
的BindView
和OnClick
,后面也没讲怎么实现RecyclerView
的事件点击,这里我利用了addOnItemTouchListener
实现单击事件,代码如下
recyclerView.addOnItemTouchListener(new RecyclerItemClickListener(this, new RecyclerItemClickListener.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
Toast.makeText(MainActivity.this, "show" + position, Toast.LENGTH_SHORT).show();
}
}));
这里的RecyclerItemClickListener
主要实现列表单击事件。代码如下
public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
private OnItemClickListener mListener;
public interface OnItemClickListener {
void onItemClick(View view, int position);
}
GestureDetector mGestureDetector;
public RecyclerItemClickListener(Context context, OnItemClickListener listener) {
mListener = listener;
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
});
}
@Override
public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
View childView = view.findChildViewUnder(e.getX(), e.getY());
if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
mListener.onItemClick(childView, view.getChildPosition(childView));
return true;
}
return false;
}
@Override
public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
这是正常的使用逻辑,但是今天我们就要用到反射去实现注解的注入,首先我们需要定义一个注解如下
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OnItemClick {
int value();
}
注解看不懂的同学建议去看一下网易云这个公开课,b站上面就有
然后主要核心就是怎么实现注入,代码如下
public class InjectManager {
public static void inject(Activity activity){
injectListOnClickEvents(activity);
}
private static void injectListOnClickEvents(final Activity activity) {
Class<? extends Activity> clazz = activity.getClass();
Method[] methods = clazz.getDeclaredMethods();
for (final Method method:methods) {
OnItemClick onItemClick= method.getAnnotation(OnItemClick.class);
if(onItemClick!=null){
int recycleViewId= onItemClick.value();
View recycleView = activity.findViewById(recycleViewId);
if(recycleView instanceof RecyclerView){
((RecyclerView) recycleView).addOnItemTouchListener(new RecyclerItemClickListener(activity, new RecyclerItemClickListener.OnItemClickListener() {
@Override
public void onItemClick(View view, int position)
{
try {
method.invoke(activity,view,position);
} catch (Exception e) {
e.printStackTrace();
}
}
}));
}
}
}
}
}
其实就是通过反射先找到当前activity的所有方法,然后通过获取方法注解找到我们注解的那个方法OnItemClick onItemClick= method.getAnnotation(OnItemClick.class);
一旦这个变量返回不为空,说明这个方法上面就有咱们的注解,具体代码注解样式如下
@OnItemClick(R.id.recycler_view)
public void OnRecycleItemClick(View view,int position){
Toast.makeText(MainActivity.this, "OnRecycleItemClick"+position, Toast.LENGTH_SHORT).show();
}
这里我们通过注解的value()
方法获取到RecyclerView
的布局ID,那我们就可以直接通过activity.findViewById(recycleViewId);
找到这个控件,然后直接就和正常的代码逻辑书写即可
((RecyclerView) recycleView).addOnItemTouchListener(new RecyclerItemClickListener(activity, new RecyclerItemClickListener.OnItemClickListener() {
@Override
public void onItemClick(View view, int position)
{
try {
method.invoke(activity,view,position);
} catch (Exception e) {
e.printStackTrace();
}
}
}));
上面有的同学看到了,在onItemClick
方法里要调用method.invoke(activity,view,position);
这里很好理解,其实就是调用其他开发人员用这个注解时,具体的点击事件处理逻辑,比如我这里是打印一个Toast
吐司
@OnItemClick(R.id.recycler_view)
public void OnRecycleItemClick(View view,int position){
Toast.makeText(MainActivity.this, "OnRecycleItemClick"+position, Toast.LENGTH_SHORT).show();
}
最后别忘了在BaseActivity
注入我们的插入代码如下
public class BaseActivity extends AppCompatActivity {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
InjectManager.inject(this);
}
}
当然你如果不希望全局用,你也可以在当前Activity
层的OnCreate
方法加入这行代码InjectManager.inject(this);
代码全部在我的github
上面会持续更新网易云微专业相关的实现代码。
网友评论