/** * @param view the parent view where the held views reside */ public ViewHolder(View view) { mView = view; FieldAnnotationParser.setViewFields(this, view); }
/** * Parse {@link LayoutId} annotation form a class * * @param myClass class that is annotated * @return the integer value of the annotation */ public static Integer getLayoutId(Class myClass) { Annotation annotation = myClass.getAnnotation(LayoutId.class); if (annotation instanceof LayoutId) { LayoutId layoutIdAnnotation = (LayoutId) annotation; return layoutIdAnnotation.value(); } return null; } }
@LayoutId(LAYOUT_ID) private static class ItemViewHolderWithLayoutId extends ItemViewHolder<Object> { ItemViewHolderWithLayoutId(View view) { super(view); } @Override public void onSetValues(Object item, PositionInfo positionInfo) { } }
public static Integer parseItemLayoutId(Class<? extends ItemViewHolder> itemViewHolderClass) { Integer itemLayoutId = ClassAnnotationParser.getLayoutId(itemViewHolderClass); if (itemLayoutId == null) { throw new LayoutIdMissingException(); } return itemLayoutId; }
/** * Parse {@link ViewId} annotation and try to assign the view with that id to the annotated field. * It will throw a {@link ClassCastException} if the field and the view with the given ID have different types. * * @param object object where the annotation is. * @param viewFinder callback that provides a way of finding the view by the viewID given in the annotation. */ private static void setViewFields(final Object object, final ViewFinder viewFinder) { Field[] fields = object.getClass().getDeclaredFields(); for (Field field : fields) { if (field.isAnnotationPresent(ViewId.class)) { field.setAccessible(true); ViewId viewIdAnnotation = field.getAnnotation(ViewId.class); try { field.set(object, field.getType().cast(viewFinder.findViewById(viewIdAnnotation.value()))); } catch (IllegalAccessException e) { e.printStackTrace(); } } } }
@LayoutId(R.layout.item_featured_event) public class FeaturedEventsAdapter extends ItemViewHolder<LocationItem> implements View.OnClickListener { @ViewId(R.id.tv_title) private TextView tvTitle; @ViewId(R.id.tv_subtitle) private TextView tvSubtitle; @ViewId(R.id.iv_location) private ImageView ivLocation; @ViewId(R.id.location_layout) private RelativeLayout locationLayout;
/** * Constructs a ActivityViewHolder using an activity * * @param activity the Activity where the held views reside */ public ActivityViewHolder(Activity activity) { mActivity = activity; FieldAnnotationParser.setViewFields(this, activity); }
/*** Test ItemViewHolders ***/ @LayoutId(LAYOUT_ID) private static class ItemViewHolderWithLayoutId extends ItemViewHolder<Object> { ItemViewHolderWithLayoutId(View view) { super(view); } @Override public void onSetValues(Object item, PositionInfo positionInfo) { } }
@Test public void testGetLayoutIdWithoutAnnotation() throws Exception{ Integer layoutId = ClassAnnotationParser.getLayoutId(ItemViewHolderWithoutLayoutId.class); Assert.assertNull(layoutId); }
@LayoutId(R.layout.item_location) public class LocationsAdapter extends ItemViewHolder<LocationItem> implements View.OnClickListener { @ViewId(R.id.tv_title) private TextView tvTitle; @ViewId(R.id.tv_subtitle) private TextView tvSubtitle; @ViewId(R.id.iv_location) private ImageView ivLocation; @ViewId(R.id.location_layout) private RelativeLayout locationLayout; @ViewId(R.id.search_layout) private RelativeLayout searchLayout; @ViewId(R.id.filters_layout) private LinearLayout filtersLayout;
/** * Parse {@link ViewId} annotation and try to assign the view with that id to the annotated field. * It will throw a {@link ClassCastException} if the field and the view with the given ID have different types. * * @param object object where the annotation is. * @param view parent view that contains a view with the viewId given in the annotation. */ public static void setViewFields(final Object object, final View view) { setViewFields(object, new ViewFinder() { @Override public View findViewById(int viewId) { return view.findViewById(viewId); } }); }
@Test public void testGetLayoutId() throws Exception{ Integer layoutId = ClassAnnotationParser.getLayoutId(ItemViewHolderWithLayoutId.class); Assert.assertTrue(layoutId.equals(LAYOUT_ID)); }
/** * Parse {@link ViewId} annotation and try to assign the view with that id to the annotated field. * It will throw a {@link ClassCastException} if the field and the view with the given ID have different types. * * @param object object where the annotation is. * @param activity activity that contains a view with the viewId given in the annotation. */ public static void setViewFields(final Object object, final Activity activity) { setViewFields(object, new ViewFinder() { @Override public View findViewById(int viewId) { return activity.findViewById(viewId); } }); }
@Test public void testSetViewFields() throws Exception { TestObjectWithAnnotations testObject = new TestObjectWithAnnotations(); FieldAnnotationParser.setViewFields(testObject, createTestLinearLayout()); Assert.assertNotNull(testObject.textView); Assert.assertNotNull(testObject.imageView); }
@Test public void testSetViewFieldsActivity() throws Exception { Activity testActivity = Robolectric.buildActivity(TestActivity.class).create().get(); TestObjectWithAnnotations testObject = new TestObjectWithAnnotations();; FieldAnnotationParser.setViewFields(testObject, testActivity); Assert.assertNotNull(testObject.textView); Assert.assertNotNull(testObject.imageView); }