源码地址:https://github.com/ldy1993/ToolforAS.git
实例二:菜单界面的注解,给某个Activity设置一个注解,该Activity自动成为菜单中某个按钮的启动Activity。
效果如下
首先创建注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MenuActivity {
MenuEnum menu();
SonMenuEnum sonMenu();
}
其中一级菜单枚举和二级菜单枚举分别如下
然后编写编译器内容。
package com.example.function.study.A_了解JAVA.F_java的高级特性.annotation.menu;
import android.app.Application;
import com.example.function.UndeterminedActivity;
import com.ldy.log.Log;
import com.ldy.study.R;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import dalvik.system.DexFile;
public class MenuActivityCompiler {
private static final String TAG = "MenuActivityCompiler";
public static final MenuModel defaultMenuModel=new MenuModel("待定", UndeterminedActivity.class, R.drawable.ic_category_0,null);
public static List<MenuModel> menuModelList;
/**
* 对所有注解了menuActivity的类进行编译
* @param application
* @param pkgName
*/
public static void menuActivityCompiler(Application application, String pkgName) {
menuModelList = new ArrayList<>();
//遍历该应用包名下,所有注解了MenuActivity的类。
List<Class<?>> classList = getClass(application, pkgName);
for (Class<?> aClass : classList) {
if (aClass.isAnnotationPresent(MenuActivity.class)) {
MenuActivity annotation = aClass.getAnnotation(MenuActivity.class);
entryMenu(aClass, annotation);
}
}
}
/**
* 录入一级菜单和二级菜单数据
*
* @param aClass
* @param annotation
*/
private static void entryMenu(Class<?> aClass, MenuActivity annotation) {
MenuEnum menuEnum = annotation.menu();
Log.e(TAG,"menuEnum.getTitle"+menuEnum.getTitle());
SonMenuEnum sonMenuEnum = annotation.sonMenu();
// 判断当前的一级菜单List大小是否够大,不够大进行扩容。
if (menuModelList.size() <= menuEnum.getIndex()) {
//扩容
expansion(menuModelList, menuEnum.getIndex());
// 因为是扩容出来的所以需要先创建一个子菜单
List<MenuModel> list = new ArrayList<>();
getSonMenuModelList(aClass, sonMenuEnum, list);
//创建一个新的一级菜单.
createMenu(null, menuModelList, menuEnum.getTitle(), menuEnum.getIcon(), list, menuEnum.getIndex());
} else {
//判断以前录入过待定还是原来就有一级菜单的
MenuModel menuModel = menuModelList.get(menuEnum.getIndex());
List<MenuModel> list;
if (!"待定".equals(menuModel.getName())) {
//不是待定。以前录入过,sonMenuModel不为空
list = menuModel.getList();
} else {
//以前没有录入过,新建一个List<MenuModel>
list = new ArrayList<>();
}
getSonMenuModelList(aClass, sonMenuEnum, list);
setMenu(aClass, menuModelList, menuEnum.getTitle(), menuEnum.getIcon(), list, menuEnum.getIndex());
}
}
/**
* 判断当前的二级菜单List大小是否够大,不够大进行扩容。扩容值为defaultMenuModel
* @param aClass
* @param sonMenuEnum
* @param list
*/
private static void getSonMenuModelList(Class<?> aClass, SonMenuEnum sonMenuEnum, List<MenuModel> list) {
if (list.size() <= sonMenuEnum.getIndex()) {
expansion(list, sonMenuEnum.getIndex());
//创建一个新的二级菜单,添加多一个
createMenu(aClass, list, sonMenuEnum.getTitle(), sonMenuEnum.getIcon(), null, sonMenuEnum.getIndex());
} else {
//创建一个新的二级菜单,设置
setMenu(aClass, list, sonMenuEnum.getTitle(), sonMenuEnum.getIcon(), null, sonMenuEnum.getIndex());
}
}
/**
* 创建一个菜单,添加
*
* @param aClass
* @param MenuList
* @param title
* @param icon
* @param sonMenuList
* @param index
*/
private static void createMenu(Class<?> aClass, List<MenuModel> MenuList, String title, int icon, List<MenuModel> sonMenuList, int index) {
MenuModel menuModel = new MenuModel(title, aClass, icon, sonMenuList);
MenuList.add(index, menuModel);
}
/**
* 创建一个菜单,设置
*
* @param aClass
* @param MenuList
* @param title
* @param icon
* @param sonMenuList
* @param index
*/
private static void setMenu(Class<?> aClass, List<MenuModel> MenuList, String title, int icon, List<MenuModel> sonMenuList, int index) {
MenuModel menuModel = new MenuModel(title, aClass, icon, sonMenuList);
MenuList.set(index, menuModel);
}
/**
* 扩容值为defaultMenuModel
*
* @param menuModelList
* @param index 扩容到index这么大
*/
private static void expansion(List<MenuModel> menuModelList, int index) {
int size = menuModelList.size();
for (int i = size; i < index; i++) {
menuModelList.add( i, defaultMenuModel);
}
}
private static List<Class<?>> getClass(Application application, String packageName) {
List<Class<?>> classList = new ArrayList<Class<?>>();
try {
DexFile df = new DexFile(application.getPackageCodePath());//通过DexFile查找当前的APK中可执行文件
Enumeration<String> enumeration = df.entries();//获取df中的元素 这里包含了所有可执行的类名 该类名包含了包名+类名的方式
while (enumeration.hasMoreElements()) {//遍历
String className = (String) enumeration.nextElement();
if (className.contains(packageName)) {//在当前所有可执行的类里面查找包含有该包名的所有类
android.util.Log.e("ldy", "获取到的类名:" + className);
try {
classList.add(Class.forName(className));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
return classList;
}
}
然后在编写一个继承了BaseExpandableListAdapter的Adapter。
package com.example.main.adapter;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.function.study.A_了解JAVA.F_java的高级特性.annotation.menu.MenuModel;
import com.ldy.study.R;
import java.util.List;
/**
* ================================================
* 作 者:刘东阳
* 版 本:
* 创建日期:2019/10/27
* 描 述:
* 修订历史:
* ================================================
*/
public class MenuActivityAdapter extends BaseExpandableListAdapter {
private Context context;
private List<MenuModel> menuModelList;
public MenuActivityAdapter(Context context, List<MenuModel> list)
{
this.context=context;
this.menuModelList=list;
}
@Override
public int getGroupCount() {
return menuModelList.size();
}
@Override
public int getChildrenCount(int groupPosition) {
try {
return menuModelList.get(groupPosition).getList().size();
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
@Override
public Object getGroup(int groupPosition) {
return menuModelList.get(groupPosition);
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return menuModelList.get(groupPosition).getList().get(childPosition);
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
/**
* 如果hasStableIds返回false的话 每次调用notifyDataSetChanged方法时
* adapter就会判断getItemId 并且在只调用那些Item发生变化的getView方法,
* 说白了就是通过getItemId来判断那些需要getView从而达到局部刷新的效果,
* 在getView比较耗时的情况下起到优化的效果。
* @return
*/
@Override
public boolean hasStableIds() {
return true;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
View view=View.inflate(context, R.layout.listview_expandable_group,null);
TextView tv= view.findViewById(R.id.textview);
tv.setText(menuModelList.get(groupPosition).getName());
return view;
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
View view=View.inflate(context, R.layout.listview_expandable_child,null);
TextView tv= view.findViewById(R.id.textview1);
tv.setText(menuModelList.get(groupPosition).getList().get(childPosition).getName());
ImageView iv= view.findViewById(R.id.imageview);
iv.setImageResource(menuModelList.get(groupPosition).getList().get(childPosition).getIcon());
return view;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition)
{
return true;
}
}
package com.example.main;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.ExpandableListView;
import android.widget.Toast;
import com.example.function.study.A_了解JAVA.F_java的高级特性.annotation.menu.MenuActivityCompiler;
import com.example.function.study.A_了解JAVA.F_java的高级特性.annotation.menu.MenuModel;
import com.example.main.adapter.MenuActivityAdapter;
import com.ldy.study.R;
import java.util.List;
/**
* 主界面
*
* @author ldy
* @date 2019/10/28
*/
public class ExpandableMainActivity extends Activity {
private ExpandableListView expandableListView;
private ExpandableListView.OnChildClickListener childClickListener = new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
MenuModel menuModel = MenuActivityCompiler.menuModelList.get(groupPosition).getList().get(childPosition);
Toast.makeText(getApplicationContext(),menuModel.getName(), Toast.LENGTH_SHORT).show();
Intent intent = new Intent(ExpandableMainActivity.this, menuModel.getClazz());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
return true;
}
};
private ExpandableListView.OnGroupExpandListener groupExpandListener = new ExpandableListView.OnGroupExpandListener() {
@Override
public void onGroupExpand(int groupPosition) {
for (int i = 0; i < MenuActivityCompiler.menuModelList.size(); i++) {
if (i != groupPosition) {
expandableListView.collapseGroup(i);
}
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_expandable);
Permission.requestPermissions(ExpandableMainActivity.this);
expandableListView = findViewById(R.id.elv);
List<MenuModel> list= MenuActivityCompiler.menuModelList;
if(list!=null&&!list.isEmpty())
{
expandableListView.setAdapter(new MenuActivityAdapter(ExpandableMainActivity.this,list));
expandableListView.setOnGroupExpandListener(groupExpandListener);
expandableListView.setOnChildClickListener(childClickListener);
}
getDisplayInfo();
}
}
并在application中引用他。
public class BaseApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
MenuActivityCompiler.menuActivityCompiler(this,"com.example.function");
}
}
最后就可以在任意的Activity中去注解了,如下