最近一直在养病,没怎么写博客了,实在很抱歉,躺在床上,翻着床头的Android开发书籍,仔细品味书的味道。
当看到ListView和GridView的时候,立刻对这两个产生了浓厚的兴趣,相信在Android的世界中,这两个控件有着重要的角色。
这两个控件的用法其实也很类似,往往都是定义一个adapter,然后重写一些方法,重要的方法就是getView那个,在getView中经常采用下面的流程
1,动态加载一个布局页面,这个布局页面相当于ListView和GridView中的一个Item
2,分别获取充当Item的这个View,然后给里面填充东西,将数据按照指定的格式显示。
大概就是这个流程。
有木有发现这个和WPF中的数据模板有点类似,关于数据模板可以在我的博客中寻找相关内容。
在这里,我们看下一个自定义的GridView:
<?xml version="1.0" encoding="utf-8"?> <GridView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/gridview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:columnWidth="90dp" android:numColumns="auto_fit" android:verticalSpacing="10dp" android:horizontalSpacing="10dp" android:stretchMode="columnWidth" android:gravity="center" />
Item的布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:layout_marginTop="5dp" > <ImageView android:id="@+id/image" android:layout_width="80dip" android:layout_height="80dip" android:layout_gravity="center_horizontal"> </ImageView> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="left" android:textSize="16dip" android:gravity="left"> </TextView> <TextView android:id="@+id/description" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="left" android:textColor="#938192" android:textSize="13dip" android:gravity="left" > </TextView> </LinearLayout>
Adapter的写法
import java.util.ArrayList; import java.util.List; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; public class GridItemAdapter extends BaseAdapter { private LayoutInflater inflater; private List<GridItem> gridItemList; public GridItemAdapter(String[] titles, int[] images,String[] description, Context context) { super(); gridItemList = new ArrayList<GridItem>(); inflater = LayoutInflater.from(context); for (int i = 0; i < images.length; i++) { GridItem picture = new GridItem(titles[i], images[i],description[i]); gridItemList.add(picture); } } @Override public int getCount( ) { if (null != gridItemList) { return gridItemList.size(); } else { return 0; } } @Override public Object getItem( int position ) { return gridItemList.get(position); } @Override public long getItemId( int position ) { return position; } @Override public View getView( int position, View convertView, ViewGroup parent ) { ViewHolder viewHolder; if (convertView == null) { convertView = inflater.inflate(R.layout.grid_item, null); viewHolder = new ViewHolder(); viewHolder.title = (TextView) convertView.findViewById(R.id.title); viewHolder.image = (ImageView) convertView.findViewById(R.id.image); viewHolder.time = (TextView) convertView.findViewById(R.id.description); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.title.setText(gridItemList.get(position).getTitle()); viewHolder.time.setText(gridItemList.get(position).getTime()); viewHolder.image.setImageResource(gridItemList.get(position).getImageId()); return convertView; }
现在的开发,有很多框架可以进行选择,这些开发框架简化了很多常用的代码,尤其是注解或者Atrribute的使用,追根到底,这些都是通过反射来完成的,在程序运行的时候
调用这些框架里面的一些方法,这些方法内部使用反射动态识别一些信息,然后将这些信息动态附加到一些操作中,如何动态识别呢?
通过XML的配置,或者注解,说得简单的一些就是元数据信息,根据这些元数据信息进行操作。
配置之后的信息,又如何被识别出来呢?
这需要一个解析操作,这个解析操作中使用了大量的反射来进行的。
我们来看下Xutils这个里面的一个方法的源码:
private static void injectObject(Object handler, ViewFinder finder) { Class<?> handlerType = handler.getClass(); // inject ContentView ContentView contentView = handlerType.getAnnotation(ContentView.class); if (contentView != null) { try { Method setContentViewMethod = handlerType.getMethod("setContentView", int.class); setContentViewMethod.invoke(handler, contentView.value()); } catch (Throwable e) { LogUtils.e(e.getMessage(), e); } } // inject view Field[] fields = handlerType.getDeclaredFields(); if (fields != null && fields.length > 0) { for (Field field : fields) { ViewInject viewInject = field.getAnnotation(ViewInject.class); if (viewInject != null) { try { View view = finder.findViewById(viewInject.value(), viewInject.parentId()); if (view != null) { field.setAccessible(true); field.set(handler, view); } } catch (Throwable e) { LogUtils.e(e.getMessage(), e); } } else { ResInject resInject = field.getAnnotation(ResInject.class); if (resInject != null) { try { Object res = ResLoader.loadRes( resInject.type(), finder.getContext(), resInject.id()); if (res != null) { field.setAccessible(true); field.set(handler, res); } } catch (Throwable e) { LogUtils.e(e.getMessage(), e); } } else { PreferenceInject preferenceInject = field.getAnnotation(PreferenceInject.class); if (preferenceInject != null) { try { Preference preference = finder.findPreference(preferenceInject.value()); if (preference != null) { field.setAccessible(true); field.set(handler, preference); } } catch (Throwable e) { LogUtils.e(e.getMessage(), e); } } } } } } // inject event Method[] methods = handlerType.getDeclaredMethods(); if (methods != null && methods.length > 0) { for (Method method : methods) { Annotation[] annotations = method.getDeclaredAnnotations(); if (annotations != null && annotations.length > 0) { for (Annotation annotation : annotations) { Class<?> annType = annotation.annotationType(); if (annType.getAnnotation(EventBase.class) != null) { method.setAccessible(true); try { // ProGuard锛?keep class * extends java.lang.annotation.Annotation { *; } Method valueMethod = annType.getDeclaredMethod("value"); Method parentIdMethod = null; try { parentIdMethod = annType.getDeclaredMethod("parentId"); } catch (Throwable e) { } Object values = valueMethod.invoke(annotation); Object parentIds = parentIdMethod == null ? null : parentIdMethod.invoke(annotation); int parentIdsLen = parentIds == null ? 0 : Array.getLength(parentIds); int len = Array.getLength(values); for (int i = 0; i < len; i++) { ViewInjectInfo info = new ViewInjectInfo(); info.value = Array.get(values, i); info.parentId = parentIdsLen > i ? (Integer) Array.get(parentIds, i) : 0; EventListenerManager.addEventMethod(finder, info, annotation, handler, method); } } catch (Throwable e) { LogUtils.e(e.getMessage(), e); } } } } } }