Learning Butterknife (series) Three

Source: Internet
Author: User
Tags unsupported

A running period


We call Butterknife.bind (this) in the OnCreate method in the activity, and we enter this method:


public static void bind (Activity target) {

Bind (target, Target, finder.activity);

}

Target is the activity, and then into the Bind method,


static void bind (object target, object source, Finder Finder) {

class<?> Targetclass = Target.getclass ();

try {

if (Debug) log.d (TAG, "Looking up view binder for" + targetclass.getname ());

1 viewbinder<object> viewbinder = Findviewbinderforclass (Targetclass);

if (Viewbinder! = null) {

2 viewbinder.bind (finder, target, source);

}

} catch (Exception e) {

throw new RuntimeException ("Unable to bind views for" + targetclass.getname (), E);

}

}

The core is 1, 2 lines of code, find Viewbinder, and then call its bind method. Targetclass is the class that the activity corresponds to and then goes into the Findviewbinderforclass method to view


private static viewbinder<object> Findviewbinderforclass (class<?> CLS)

Throws Illegalaccessexception, Instantiationexception {

viewbinder<object> Viewbinder = Binders.get (CLS);

if (Viewbinder! = null) {

if (Debug) log.d (TAG, "hit:cached in view Binder map.");

return viewbinder;

}

String clsname = Cls.getname ();

if (Clsname.startswith ("Android.") | | clsname.startswith ("java.")) {

if (Debug) log.d (TAG, "miss:reached Framework class. Abandoning search. ");

return nop_view_binder;

}

try {

1 class<?> viewbindingclass = class.forname (Clsname + "$ $ViewBinder");

Noinspection unchecked

2 Viewbinder = (viewbinder<object>) viewbindingclass.newinstance ();

if (Debug) log.d (TAG, "hit:loaded View Binder class.");

} catch (ClassNotFoundException e) {

if (Debug) log.d (TAG, "not found. Trying Superclass "+ Cls.getsuperclass (). GetName ());

Viewbinder = Findviewbinderforclass (Cls.getsuperclass ());

}

Binders.put (CLS, viewbinder);

return viewbinder;

}

The core code is based on the principle of simple reflection, is to construct an instance of a class, what is this class, according to the previously known CLS is activity, we are mainactivity with annotations bind, that CLS is mainactivity,


Clsname + "$ $ViewBinder"

The concatenation of the string is the maintivity$ $ViewBinder, exactly the name of the source file created at compile time, after the execution of 2, we have obtained an instance of this class. Cut back


static void bind (object target, object source, Finder Finder)

The 2-line code in this method calls the Bind method in the class instance corresponding to the source file class. Let's see again what this source file does in the Bind method.


public class mainactivity$ $ViewBinder <t extends com.hsj.weather.ui.activity.mainactivity> implements viewbinder<t> {

@Override public void bind (Final finder finder, final T target, Object source) {

View view;

1 view = Finder.findrequiredview (source, 2131361899, "Field ' Iv_title_left '");

2 Target.iv_title_left = Finder.castview (view, 2131361899, "Field ' Iv_title_left '");

View = Finder.findrequiredview (source, 2131361901, "Field ' Iv_title_right '");

Target.iv_title_right = Finder.castview (view, 2131361901, "Field ' Iv_title_right '");

View = Finder.findrequiredview (source, 2131361900, "Field ' Tv_title_center '");

Target.tv_title_center = Finder.castview (view, 2131361900, "Field ' Tv_title_center '");

}


@Override public void Unbind (T target) {

Target.iv_title_left = null;

Target.iv_title_right = null;

Target.tv_title_center = null;

}

}

We can look at the corresponding code


See 1,finder called Findrequiredview (), the Finder is an enumeration field for Butterknife. This finder's code is more important to paste,

public enum finder {  view {     @Override  protected  view findview (Object source, int id)  {       return  (View)  source). Findviewbyid (ID);    }     @Override  public context getcontext (Object source)  {      return   (View)  source. GetContext ();    }     @Override   Protected string getresourceentryname (Object source, int id)  {       final View view =  (View)  source;       // in edit mode, getresourceentryname ()  is unsupported due to  use of BridgeResources      if  (View.isineditmode ())  {         return  "<unavailable while editing>";       }       return super.getresourceentryname (Source, id);     }  },  ACTIVITY {     @Override  protected view  findview (Object source, int id)  {      return  (( Activity)  source. Findviewbyid (ID);    }     @Override  public  context getcontext (Object source)  {      return  ( Activity)  source;    }  },  DIALOG {     @Override  protected view findview (object source, int id)  {       return  ((Dialog)  source). Findviewbyid (ID);    }      @Override &NBSp;public context getcontext (Object source)  {      return   ((Dialog)  source). GetContext ();    }  };  private  Static <t> t[] filternull (t[] views)  {    int end  = 0;    for  (int i = 0; i < views.length;  i++)  {      T view = views[i];       if  (view != null)  {        views[end++ ] = view;      }    }     Return arrays.copyofrange (views, 0, end);  }   @SafeVarargs    Public static <t> t[] arrayof (t... views)  {    return  filternull (views); &NBSP;&NBSP;}    @SafeVarargs   public static <t> list<t> listof (T ...  views)  {    return new ImmutableList<> (Filternull (views));   }  public <t> t findrequiredview (Object source, int  id, string who)  {    t view = findoptionalview (source,  id, who);    if  (view == null)  {       string name = getresourceentryname (Source, id);       Throw new illegalstateexception ("required view "            + name          +  "'   with id  "          + id           +  " for "           + who           +  " was not found. if  this view is optional add  ' @Nullable '  annotation. ");     }    return view;  }  public <t > t findoptionalview (object source, int id, string who)  {     view view = findview (Source, id);    return  Castview (view, id, who);  }   @SuppressWarnings ("unchecked")  // that ' s  the point.  public <t> t castview (View view, int id,  string who)  {    try {      return   (T) &NBSP;VIEW;&NBSP;&NBSP;&NBSP;&NBSP;}&NBSP;CATCh  (classcastexception e)  {      if  (who == null)  {        throw new assertionerror ();       }      string name = getresourceentryname (View,  id);       throw new illegalstateexception ("View "            + name           +  '  with ID  '            + id          +  " for "            + who           +  " was of the wrong type. See cause for  More info. ",  e);    }  }   @SuppressWarnings ("unchecked")  // that ' s the  Point.  public <t> t castparam (object value, string from,  Int fromposition, string to, int toposition)  {    try {       return  (T)  value;    } catch  ( Classcastexception e)  {      throw new illegalstateexception ("parameter #"           +  (fromposition +  1)           +  " of method "            + from           +  "'  was of the wrong type for parameter #"           +  (toposition + 1)            +  " of method "            + to          +  "'.  see cause  for more info. ",  e);     }  }

View findrequiredview () method (according to the previous compile period to create the source code, you know, this finder type is Span style= "FONT-SIZE:13.3333PX; line-height:24px; " >finder. ACTIVITY), so T is finder. activity :

Public <t> t findrequiredview (object source, int id, string who)  {  t view = findoptionalview (source, id, who);  if  ( View == null)  {    string name = getresourceentryname (source ,  id);     throw new illegalstateexception ("required view "          + name        +  "'  with ID  "        + id         +  " for "         + who         +  " was not found. If this  view is optional add  ' @Nullable '  annotation. ");   }  return view;}

Enter the Findoptionalview method,

Public <T> T Findoptionalview (Object source, Int. ID, String WHO) {View view = Findview (source, id); Return Castview (view, id, who);}

To enter the Findview method:

Protected abstract View Findview (Object source, int id);

Discovery is its abstract method, who implements it, looking at the Finder enumeration

view {   @Override  protected view findview (object source, int id)  {    return  (View)  source. Findviewbyid (ID);   }  @ Override public context getcontext (Object source)  {    return   (View)  source. GetContext ();  }   @Override  protected String  Getresourceentryname (Object source, int id)  {    final View  view =  (View)  source;    // In edit mode,  Getresourceentryname ()  is unsupported due to use of BridgeResources     if  (View.isineditmode ())  {      return  < Unavailable while editing> ";    }    return  Super.getresourceentryname (source, id);   }},activity {   @Override  protected view findview (Object source,  int id)  {    return  (Activity)  source. Findviewbyid (ID);   }   @Override  public context getcontext (object source)  {     return  (Activity)  source;  }},DIALOG {   @Override   Protected view findview (Object source, int id)  {    return   ((Dialog)  source). Findviewbyid (ID);  }   @Override  public context  getcontext (Object source)  {    return  ((Dialog)  source). GetContext ();  }};

Because that T is the Finder. ACTIVITY, so will call Finder.activity's Findview method, the method to see a sentence to write a bad sentence code:

(Activity) source). Findviewbyid (ID);

is to use the Findviewbyid to get the view. Now switch to the bind method of the mainactivity$ $ViewBinder

  @Override  public void bind (Final finder finder, final t target,  object source)  {    view view;    view =  finder.findrequiredview (source, 2131361899,  "field  ' Iv_title_left '");1     target.iv_title_left = finder.castview (view, 2131361899,  "field  ' Iv_title_left ' ");     view = finder.findrequiredview (source, 2131361901, " field  ' Iv_title_right ');     target.iv_title_right = finder.castview (view,  2131361901,  "field  ' Iv_title_right '");    view =  Finder.findrequiredview (source, 2131361900,  "field  ' Tv_title_center '");     Target.tv_title_center = finder.castview (view, 2131361900,  "field  ' Tv_title_center '") ;   }

Target is an instance of mainactivity, and the variable iv_title_left executed in Mainactivity is assigned, and in this activity you can use iv_title_left directly, for example.

Iv_title_left.setimageresource (R.drawable.btn_addcity_normal);


In the activity we rewrote the OnDestroy:

@Overrideprotected void OnDestroy () {//TODO auto-generated method Stubsuper.ondestroy (); Butterknife.unbind (this);}

Butterknife.unbind () call, we can guess inside is called, that source file class in the UnBind () method.

In the Unbind () method, these variables are assigned a value of NULL. Release the memory.


Butterknife in the compilation and operation of the operating mechanism of the principle is almost here, for other annotation elements, such as bindbitmap,binddimen, and so on, the bottom is called the method we usually get resources.




Learning Butterknife (series) Three

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.