Preface
Why summarize the use of generics? How does generics represent value in a project? Don't talk about it. Summarize it. From practice to theory, finally return to generic nature.
1. What is generics? Why generics?
Definition:
Generics: the "broad data type", any data type.
Effect:
- Generics can solve the security problem of data types. The main principle of generics is to represent the type of a property in a class or the return value and parameter type of a method through an identifier when a class is declared
- In development, it is often used for code abstraction and encapsulation to make it tool and general. It can effectively reduce the code redundancy and make the code more readable.
In the ArrayList source code, you can find the use of generics everywhere.
public class ArrayList<E> extends AbstractList<E>
public boolean addAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index); boolean modified = false; for (E e : c) { add(index++, e); modified = true; } return modified; }
Note:
-
Generics are usually represented by < > and a capital letter, while there are four ways commonly used, namely < T >, <? >, < extends Object >, < super Object >.
- In which, T represents the same type, and T represents the same type,? Represents any type, < extends xx > represents type xx, and the child of type xx <? Super xx > represents type xx, and the parent of type xx.
- Class < T >: when instantiating, you need to specify a specific type Class <? >: can represent all types.
- It is not recommended to use such a wonderful way of definition as < g >, < Q >.
- Generics cannot use basic data types, such as int, double, etc., but only their container classes, such as Integer, double, etc. Because Java's generics are implemented by type erasure, and objects are used at runtime, and basic data types are not inherited from objects, so they cannot be used in generics.
-
out and in in Kotlin
Like Java generics, generics in Kolin are immutable.
- Using the keyword out to support covariance is equivalent to the upper bound wildcard "extends" in Java.
Foo<? extends Bar>
CorrespondingFoo<out Bar!>!
- Using the keyword in to support inversion is equivalent to the lower bound wildcard super in Java.
Foo<? supter Bar >
CorrespondingFoo<in Bar!>!
- Using the keyword out to support covariance is equivalent to the upper bound wildcard "extends" in Java.
2. Usage scenarios in Android
2.1 use change of findviewbyid
/** * FindViewById Reduce strong conversion code */ public <T extends View> T findViewById(@IdRes int id) { return getDelegate().findViewById(id); } //Before use: Button btnReload =(Button) findViewById(R.id.btn_reload); //Now: Button btnReload = findViewById(R.id.btn_reload);
After the continuous iteration of Android version, it must be forced to convert from the beginning to the later when the generic encapsulation has been implemented internally. Of course, now that Kotlin is popular, this step can be omitted directly.
2.2 BaseAdapter implements the encapsulated Adapter
When ListView is widely used, we usually encapsulate an Adapter like this.
public abstract class CommonAdapter<T> extends BaseAdapter { protected LayoutInflater mLayoutInflater; protected List<T> mDatas; protected Context mContext; public CommonAdapter(Context mContext) { this.mContext = mContext; } public CommonAdapter(List<T> mDatas, Context mContext) { this.mDatas = mDatas; this.mContext = mContext; } public CommonAdapter(LayoutInflater mLayoutInflater, List<T> mDatas, Context mContext) { this.mLayoutInflater = mLayoutInflater; this.mDatas = mDatas; this.mContext = mContext; } @Override public int getCount() { return mDatas.size(); } @Override public T getItem(int position) { return mDatas.get(position); } @Override public long getItemId(int position) { return position; } @Override public abstract View getView(int position, View convertView, ViewGroup parent); }
When RecycleView was born, we can use generics in this way. For details, see the summary of the use of RecycleView in this article, Click to go
The Adapter usually needs to accept a data or collection, but the data type is uncertain, so it's natural for scenarios like this to use generics because they want to accept a wide range of data types. Generality is one of the benefits of generics.
2.3 network request data
In development, the json data returned when the network requests data is generally long, such as returning a user information:
"code": 0, "message": "success", "data": { "token": "pbGUiLCJuYmYiOjE1NzI4NTg0NjIsInN1YiI6IjMxNDQifQ.YJ2A1wl2Jo9hbyRfkMlthoMkhfuKtlZh0vrkgi-rPpw", "uid": "a41b3bb3e6b050b6c915", "phone": "13908213909", "name": "Little lamb said", "shopName": "Chengdu Yintai City", "authTrueName": 1 } }
Or return a grouping information:
"code": 0, "message": "Success", "data": { "groups": [ { "name": "I love you China", "count": 12, "groupId": 116 }, { "name": "One born with a silver spoon in one's mouth", "count": 1, "groupId": 97 }, { "name": "Tall, rich and handsome", "count": 2, "groupId": 96 }, { "name": "Undefined group", "count": 21886, "groupId": -1 } ], "linkman": "Valuable" } }
The key values in the code, message and data fields are the same, which can be understood as the common basic data is the same, no matter what data the server returns, these are the same.
Only the data in data is different, which can be understood as different demand data.
Once we find the common return information, we can start to generalize the encapsulation. BaseBean is to encapsulate the basic data.
First, encapsulate the generic BaseBean:
public class BaseBean<T> { public int code; public String message; public T data; @Override public String toString() { return "code: " + code + "\nmessage: " + message + "\ndata: " + data; } }
It's much more convenient to use.
//Such as the implementation class in the detection version information public class VersionBean extends BaseBean<VersionBean.DataBean> { public static class DataBean { public String appname; //App application name public String detailhtml; //Update details public String downloadurl;//Channel download address public String downloadurl_common; //Universal download address standby public String detail; //Update details public String updatetime; public String version; //Version name as version "1.1.2" public int versionCode;//Version No. every upgrade public int isforceupdate; //Do you want to force upgrade as 0 normal upgrade 1 forced upgrade } } //Such as entity class in the list returned by multiple keywords public class KeywordBean extends BaseBean<List<KeywordBean.KeyWord>> { public static class KeyWord { public int id; public String title; } }
At the same time, modify the returned data type in combination with the RxJava+Retrofit request interface:
@GET("getAppVersion.php") Observable<VersionBean> checkVersion(@Query("deviceType") int deviceType, @Query("channel") String channel, @Query("versionCode") int versionCode); @GET("keyWords.php") Observable<KeywordBean> keyWord();
The generic simple examples in network requests are introduced here first. For specific use, please refer to my previous summary, Click to go
2.4 other application scenarios
For example, MVP architecture is used in the development, which will also be used. It's important to be familiar with generics.
How to use generics and abstractions to optimize the structure of MVP has become the key to make good use of MVP. Of course, we can abstract some common models and presenters through generic parameters and abstract parent classes. This should be the essence of using MVP architecture.
3. summary
Generics are widely used in development and will be updated in the future.
Extended reading: