smilevchy
4/2/2018 - 9:37 AM

A simple way to bind/inject view without writing too much findViewById(R.id.xxx) template code.

A simple way to bind/inject view without writing too much findViewById(R.id.xxx) template code.

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface BindView {
    int value() default 0;
    String id() default "";
}
import android.app.Activity;
import android.content.res.Resources;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class BindSimple {
    private static final String TAG = BindSimple.class.getSimpleName();

    private BindSimple() {
        // no-op
    }

    public static void bind(Object object) {
        Activity activity = null;
        Fragment fragmentV4 = null;
        android.app.Fragment fragment = null;

        if (object instanceof Activity) {
            activity = (Activity) object;
        } else if (object instanceof Fragment) {
            fragmentV4 = (Fragment) object;
        } else if (object instanceof android.app.Fragment) {
            fragment = (android.app.Fragment) object;
        } else if (object instanceof View) {
            view = ((View) object);
        } else {
            throw new IllegalArgumentException("object must be instance of either Activity or Fragment");
        }

        Resources res = null;

        if (activity != null) {
            res = activity.getResources();
        } else if (fragmentV4 != null) {
            res = fragmentV4.getResources();
        } else if (fragment != null) {
            res = fragment.getResources();
        } else if (view != null) {
            res = view.getResources();
        }

        if (res == null) {
            throw new IllegalStateException("res is null");
        }

        Field[] fields = object.getClass().getDeclaredFields();

        for (Field f : fields) {
            Class<?> type = f.getType();

            if (!View.class.isAssignableFrom(type)) {
                continue;
            }

            try {
                BindView annotation = f.getAnnotation(BindView.class);

                if (annotation == null) {
                    continue;
                }

                f.setAccessible(true);

                if (annotation.value() != 0) {
                    injectView(f, object, annotation.value());
                } else if (!TextUtils.isEmpty(annotation.id())) {
                    String packageName = "";

                    if (activity != null) {
                        packageName = activity.getPackageName();
                    } else if (fragmentV4 != null) {
                        packageName = fragmentV4.getActivity().getPackageName();
                    } else if (fragment != null) {
                        packageName = fragment.getActivity().getPackageName();
                    } else if (view != null) {
                        packageName = view.getContext().getPackageName();
                    }

                    int id = res.getIdentifier(annotation.id(), "id", packageName);
                    if (id != 0) {
                        injectView(f, object, id);
                    }
                }
            } catch (IllegalAccessException e) {
                Log.e(TAG, e.toString());
            } catch (NoSuchMethodException e) {
                Log.e(TAG, e.toString());
            } catch (InvocationTargetException e) {
                Log.e(TAG, e.toString());
            }
        }
    }

    private static void injectView(Field f, Object object, int id) throws IllegalAccessException,
            NoSuchMethodException, InvocationTargetException {
        if (object instanceof Activity) {
            f.set(object, ((Activity) object).findViewById(id));
        } else if (object instanceof Fragment || object instanceof android.app.Fragment) {
            Method getViewMethod = object.getClass().getMethod("getView");
            Object rootView = getViewMethod.invoke(object);
            f.set(object, ((View) rootView).findViewById(id));
        } else if (object instanceof View) {
            f.set(object, ((Activity) object).findViewById(id));
        }
    }
}