標籤:android
註解在android程式中的使用
何為註解:
在Java當中,註解又叫做“中繼資料”,它為我們在原始碼中添加資訊提供了一種形式化的方法,讓我們能在以後的某個時間方便的使用這些資料。更確切的說,註解在一定的程度上將資料與元代碼進行了綁定,並不是將資料儲存在外部檔案中。當然,這裡只介紹Android開發相關的技術,至於註解我會在Java學習總結篇中進行詳細的研究和總結。那麼,接下來我們一個執行個體來介紹註解在android開發中的巧妙應用。
執行個體描述:
在這裡,我們使用註解替換掉android中初始化資來源物件的findViewById(...)方式,具體如下代碼所示:
我的項目結構:
註解部分:
ContentView.java:
/**
* inject contentview
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ContentView {
int value() default 0;
}
InjectView.java:
/**
* inject view of contentview
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ViewInject {
int value();
int parentResId() default 0;
}
資源初始化部分:
ViewInjectObj.java:
int parentResId;
Object value;
@Override
public boolean equals(Object obj) {
boolean result;
if(this == obj) {
result = true;
}
if(!(obj instanceof ViewInjectObj)) {
result = false;
}
ViewInjectObj that = (ViewInjectObj) obj;
if(parentResId != that.parentResId) {
result = false;
}
if(null == value) {
return result = (null == that.value);
}
result = value.equals(that.value);
return result;
}
@Override
public int hashCode() {
int result = value.hashCode();
result = 35 * result + parentResId;
return result;
}
@Override
public String toString() {
return "ViewInjectObj [parentResId=" + parentResId + ", value=" + value
+ "]";
}
ViewSelector.java:
/**
* find view id resources
*/
public class ViewSelector {
private Activity currActivity;
private View currView;
public ViewSelector(Activity activity) {
currActivity = activity;
}
public ViewSelector(View view) {
currView = view;
}
public View findViewById(int id) {
return null == currView ? currActivity.findViewById(id) : currView.findViewById(id);
}
public View findViewByInfo(ViewInjectObj info) {
return findViewById((Integer) info.value, info.parentResId);
}
public View findViewById(int id,int pId) {
View pView = null;
if(0 < pId) {
pView = findViewById(pId);
}
View currView = null;
if(null != pView) {
currView = pView.findViewById(id);
} else {
currView = findViewById(id);
}
return currView;
}
}
映射方法部分:
InjectConfig.java:
/**
* inject view methods
*/
public class InjectConfig {
static final String TAG = "InjectConfig";
public InjectConfig() {
}
// inject contentview
public void injectContentView(Object obj,Class<?> objClass) {
ContentView contentView = objClass.getAnnotation(ContentView.class);
if(null != contentView) {
try {
Method method = objClass.getMethod("setContentView", int.class);
method.invoke(obj, contentView.value());
} catch(Throwable tr) {
Log.e(TAG, tr.getMessage(), tr);
}
}
}
// inject view
public void injectView(Object obj,ViewSelector viewSelector,Class<?> objClass) {
Field[] fields = objClass.getDeclaredFields();
if(null != fields && 0 < fields.length) {
for(Field field : fields) {
ViewInject viewInject = field.getAnnotation(ViewInject.class);
if(null != viewInject) {
try {
View view = viewSelector.findViewById(viewInject.value(), viewInject.parentResId());
if(null != view) {
field.setAccessible(true);
field.set(obj, view);
}
} catch(Throwable tr) {
Log.e(TAG, tr.getMessage(), tr);
}
}
}
}
}
}
調用工具部分:
ViewUtilSvc.java:
public class ViewUtilSvc {
static InjectConfig config = null;
public static void inject(Activity activity) {
inject(activity,new ViewSelector(activity));
}
public static void inject(View view) {
inject(view,new ViewSelector(view));
}
public static void inject(Object obj, View view) {
inject(obj, new ViewSelector(view));
}
static void inject(Object obj,ViewSelector viewSelector) {
if(null == config) {
config = new InjectConfig();
}
Class<?> objClass = obj.getClass();
config.injectContentView(obj, objClass);
config.injectView(obj, viewSelector, objClass);
}
}
前台顯示部分:
MainActivity.java:
@ContentView(R.layout.activity_main)
public class MainActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
ViewUtilSvc.inject(this);
if (savedInstanceState == null) {
getSupportFragmentManager()
.beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
}
public static class PlaceholderFragment extends Fragment {
@ViewInject(R.id.tvHelloWorld)
TextView tvHelloWorld;
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,false);
ViewUtilSvc.inject(this,rootView);
String hello = getResources().getString(R.string.text_helloworld_tv);
tvHelloWorld.setText(hello);
return rootView;
}
}
}
正如上面代碼所示,我們使用了註解在代碼中動態添加了資料,然後藉助反射機制來獲得註解的資料;
使用了@ContentView(...) 替代了原生的setContentView(...)部分,使用了ViewUtilSvc.inject(...)進行對應的注射即可。另外,這樣的做的目的就是為了簡化物件檢視的初始化工作。具體的運行如下所示:
好了,到這裡我們的TextView上的hello world終於顯示出來了,如果有任何問題的話,請在評論中進行發問討論。
/**
* 技術交流QQ群:179914858
*/