A cliche
- What is the
Retrofit
? Retrofit
This is not a new technology, and everyone reading this blog is already familiar with it, so I will not be verbose here, but a brief introduction:- Retrofit is designed for Java and Android
REST
The client. It works by building onREST
Web services to retrieve and upload JSON (or other structured data) relatively easily. In use, you can configure the converter for data serialization. For JSON, it is usually usedGson
, but you can add custom converters to handle itXML
Or other agreements. Retrofit is used for HTTP requestsOkHttp
Library.
A type-safe HTTP client for Android and Java
- Ok, the introduction is over, I think everyone’s big knives are hungry, so let’s start straight away
In this paper, the process
Dependency injection
- So Easy
- In the App Module
build.gradle
Add the following dependencies to:
// OkHttp3
api 'com. Squareup. Okhttp3: okhttp: 3.10.0'
api 'com. Squareup. Okio: okio: 1.8.0 comes with'
// Retrofit
api 'com. Squareup. Retrofit2: retrofit: 2.7.0'
// Gson server data interaction
api 'com. Google. Code. Gson: gson: 2.8.6'
Copy the code
Dependency injection is very simple, Retrofit has always been a combination of OkHttp and Gson (I don’t care what JSON parser I’m using here)
- Don’t worry. I told you that before
Retrofit
Is combined withOkHttp
Do network request, so carefully remind to open the network permissions:
<uses-permission android:name="android.permission.INTERNET" />
Copy the code
Comprehensive rashly
- About online
Retrofit
The tutorial is full of things, but it always gives a feeling of fog and fog - So the great thing about this article is that I’m going to use my own actual project code to show you what Retrofit is all about
Before Retrofit started
- Here I will use the login module of my open source project FIWKeepApp as an example
- in
Retrofit
Before the emergence of the primitive society, we generally conducted network requests like this:
public void login2(a) {
OkHttpClient okHttpClient = new OkHttpClient();
//Form passes parameters in the Form format
FormBody formBody = new FormBody
.Builder()
// Set the parameter name and value
.add("username",mAccountEdit.getText().toString())
.add("password",mPasswordEdit.getText().toString())
.build();
Request request = new Request
.Builder()
// The parameters of the Post request are passed
.post(formBody)
.url("http://hyh.hljdx.net:8080/SitUpWebServer/login")
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(okhttp3.Call call, IOException e) {
Log.d("my_Test", e.getMessage());
}
@Override
public void onResponse(okhttp3.Call call, Response response) throws IOException {
String result = response.body().toString();
UserBean userBean = JSON.parseObject(result, UserBean.class);
Log.d("my_Test",userBean.getUser_head_img()); response.body().close(); }}); }Copy the code
- Is there a feeling of being in a fog?
- The first thing you need to do is wrap the form information you want to send as
Post
The request ofBody
Object, so some students will ask what isPOST
And what isBody
? This is a question for youGoogle
Here I suggest you learn some back-end or network knowledge, very simple and very necessary - And then you need to encapsulate another one
Request
Object, which is the body of our request, sets up where the information should be submitted - The last call
okHttpClient
The corresponding method sends a combination of the previously implemented things and receives them in a callback - So, step by step, encapsulation again
FormBody
Is encapsulatedRequest
I still need it after a long timeokHttpClient
Send, a set down dizziness, so how to solve it? - then
Retrofit
The savior appeared
Retrofit implementation
- Again, the login module in my project, which I changed to
Retrofit
In the form of - Also complete the above function if used
Retrofit
Implementation only requires:
// baseUrl() sets the routing address
Retrofit retrofit = new Retrofit
.Builder()
.baseUrl(ApiUtils.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
// Set parameters
Call<UserBean> call = retrofit.create(UserMgrService.class)
.login( mAccountEdit.getText().toString(),
mPasswordEdit.getText().toString());
/ / callback
call.enqueue(new Callback<UserBean>() {
@Override
public void onResponse(Call<UserBean> call, Response<UserBean> response) {
Log.d("123123"."msg--" + response.body().getUser_head_img());
}
@Override
public void onFailure(Call<UserBean> call, Throwable t) {
// Handle failure}});Copy the code
- The sum pure is realized as above
okHttp
Code like functionality - And you might say, well, that’s not that easy, right? But a closer look reveals the first step
Retrofit
The instantiation process is almost constant as long as the server does not change the code, so we can completely encapsulate it
- And did you notice that if you just use
OkHttp
Our return value is oneResponse
Object, which we also need to extract fromJSON
Object to perform type conversion while inRetrofit
Because of the data parser, this chunk of code is omitted - There are a lot of advantages, here is not nagging, we directly began to learn the way to use it!
The implementation process
- So now I’m going to explain each of these steps
Create the interface
- First we will create the UserMgrService interface
/ * * *@author fishinwater-1999
* @versionThe 2019-12-21 * /
public interface UserMgrService {
/** * GET uses Query */
@GET("login")
Call<UserBean> login(@Query("username") String username, @Query("password") String password);
}
Copy the code
- from
@GET()
You can guess from the notes that this is going to be aGet
request - We’re looking at the method body, and the return value will be a wrapper
UserBean
的Call<>
object - There are two parameters, respectively
String username
和String password
- Unlike the usual method, these two parameters are carried separately
@Query("..." )
annotations - through
@Query("..." )
We find that this is related tookHttp
createFormBody
When,add
The parameters coincide
If you don’t already know what a Get request is, and @query (“…” For example, if we open a web page at random, take baidu image search Github page as an example:
- The backend write server will pass these parameters like
A HashMap get (" key ")
I’m going to take the same values
POST
- I think you’ll get the idea
- In addition to
GET
There’s another wayPOST
Method, compared to usingGET
, the use ofPOST
There are many other advantages that I won’t go into here - He use and
GET
Same idea if you usePOST
Our code would look like this:
public interface UserMgrService {
/** * POST uses Field */
@POST("login")
@FormUrlEncoded
Call<UserBean> login(@Field("username") String username, @Field("password") String password);
}
Copy the code
- You just change the name of the note and put it in
@POST("..." )
Let’s add another one@FormUrlEncoded
annotations - Without further ado, let’s go straight to the next step
Generate Retrofit objects
- Let’s take a look at how to create and set it:
// baseUrl() sets the routing address
Retrofit retrofit = new Retrofit
.Builder()
.baseUrl(ApiUtils.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
Copy the code
- So this is basically two steps, setup
baseUrl
Set up the data parser - Same old what is it
baseUrl
? Just take what I used beforeOkHttp
Take the url you set as an example
http://hyh.hljdx.net:8080/SitUpWebServer/login
Copy the code
- You can think of it this way: the top one
url = baseurl + @GET("..." )
The string passed in the annotation - If we set it to be
@GET("login")
That herebaseurl
Is this:http://hyh.hljdx.net:8080/SitUpWebServer/
It was obvious all at once, but other bloggers don’t take care of newcomers and never make it clear - Then there is the data parser. You may recall that we imported a tripartite library at the beginning:
// Gson server data interaction
api 'com. Google. Code. Gson: gson: 2.8.6'
Copy the code
- Our data, and the server’s data, is based on
JSON
Interactive in the form of, for exampleBing
Daily Wallpaper Interface
- When you set up the data parser, you can automatically encapsulate the returned information into corresponding objects, you see
How to obtain this object, you can contact the backend, or Baidu search JsonFormat plug-in or JSON object generator, many ways here tell you
Generating interface objects
- As usual, let’s look at the code
UserMgrService service = retrofit.create(UserMgrService.class);
Copy the code
- Too simple, call before
retrofit
The object’screate()
Method passed into the interfaceclass
file
Get the Call object
- We know that from the code we started with
- We send a request to the server that needs to be called
call
The object’senqueue()
methods - then
Call
How do you get objects? It’s really simple:
Call<UserBean> call = service.login( mAccountEdit.getText().toString(), mPasswordEdit.getText().toString());
Copy the code
- In plain English, it calls the corresponding method of the interface directly, and it returns one directly
Call
object
Send the request
- There are two types of requests: synchronous and asynchronous
- Because requests are time consuming, if we send a synchronous request, the application will block before the request is returned
- To put it bluntly, will be stuck, even stuck to death… So this request is rarely used
- Although not, but responsible I still give you the code:
Response<UserBean> response = call.execute();
Log.d("123123"."msg--" + response.body().getUser_head_img());
Copy the code
- I don’t want to talk about it. It’s called
call
的execute()
Will return a value - This value is the result of the request, you can use it directly (but in this only return, such as slow connection, the phone can be stuck or even
ANR
) - Here I introduce asynchronous requests:
/ / callback
call.enqueue(new Callback<UserBean>() {
@Override
public void onResponse(Call<UserBean> call, Response<UserBean> response) {
Log.d("123123"."msg--" + response.body().getUser_head_img());
}
@Override
public void onFailure(Call<UserBean> call, Throwable t) {
// Handle failure}});Copy the code
- This is the asynchronous method, called directly
call
的enqueue
Method, passing in aCallback
The interface can be - The system automatically releases the resource without blocking until the result of the request is returned
- It’s automatically called
onResponse
The method, the methodresponse
That’s the result of the processing - After this code runs the result Demo Example is not particularly simple!
Login function combat
- I think you’ve all learned it by now
Retrofit
The use of - So let’s take the login function as an example and see how it can be referenced in a project
Retrofit
- The actual combat part of the pre-condition is
MVP
+ButterKnife
It’s easy to find information on the Internet
Set up the Model layer
- Create the interface
ILoginModel
- The interface exposes the Username password and a listening callback interface (the interface is passed in via generics)
/ * * *@author fishinwater-1999
* @versionThe 2019-11-12 * /
public interface IBaseLog<L> {
/** * login Api *@param userAccount
* @param mPassword
* @param loginCallback
*/
void login(String userAccount, String mPassword, L loginCallback);
}
Copy the code
- Implement the callback interface
- Observer mode, which dynamically notifies layer P when a request message is returned
/ * * *@author fishinwater-1999
* @versionThe 2019-12-23 * /
public interface IBaseRetCallback<T> {
void onSucceed(Response<T> response);
void onFailed(Throwable t);
}
Copy the code
- create
LoginModel
implementationILoginModel
interface - implementation
login
Method to call back after a successful requestIBaseRetCallback
Listening to the
/ * * *@author fishinwater-1999
* @versionThe 2019-11-12 * /
public class LogViewModel implements IBaseLog<IBaseRetCallback<UserBean>> {
private final String TAG = "LogViewModel";
@Override
public void login(String userAccount, String userPassword, final IBaseRetCallback<UserBean> retCallback) {
// baseUrl() sets the routing address
Retrofit retrofit = new Retrofit
.Builder()
.baseUrl(ApiUtils.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
// Set parameters
UserMgrService service = retrofit.create(UserMgrService.class);
retrofit2.Call<UserBean> call = service.login( userAccount, userPassword);
/ / callback
call.enqueue(new Callback<UserBean>() {
@Override
public void onResponse(retrofit2.Call<UserBean> call, Response<UserBean> response) {
retCallback.onSucceed(response);
}
@Override
public void onFailure(retrofit2.Call<UserBean> call, Throwable t) {
// Handle failureretCallback.onFailed(t); }}); }}Copy the code
To build the Presenter layer
- First of all achieve
Presenter
Layer of the base class - Again, build
Presenter
The layer base class first implements the interface
/ * * *@author fishinwater-1999
* @versionThe 2019-11-12 * /
public interface IBasePresenter<V> {
/** * bind *@param mLogView
*/
void attachView(V mLogView);
/** * unbind */
void detachView(a);
/** * login *@param userName
* @param userPassword
* @param resultListener
*/
void login(String userName, String userPassword, V resultListener);
}
Copy the code
- Writing abstract classes
BasePresenter
implementationIBasePresenter
interface
/ * * *@author fishinwater-1999
* @versionThe 2019-11-12 * /
public abstract class BasePresenter<V> implements IBasePresenter<V> {
private V view;
@Override
public void attachView(V mLogView) {
this.view = mLogView;
}
@Override
public void detachView(a) {
this.view = null;
}
@Override
public V getLoginVew(a) {
return this.view; }}Copy the code
- And then we get to our specific
LogPresenter
The realization of the class LogPresenter
Classes need to hold View layer and Model layer interfaces
/ * * *@author fishinwater-1999
* @versionThe 2019-11-12 * /
public class LogPresenter extends BasePresenter<ILoginView> {
private IBaseLog logViewModel;
public LogPresenter(IBaseLog logViewModel) {
this.logViewModel = logViewModel;
}
@Override
public void login(String userName, String userPassword, final ILoginView iLoginView) {
logViewModel.login(userName, userPassword, new IBaseRetCallback<UserBean>() {
@Override
public void onSucceed(Response<UserBean> response) {
UserBean userBean = response.body();
if(userBean ! =null) { String user_id = userBean.getUser_id(); iLoginView.showLoginSuccess(user_id); }}@Override
public void onFailed(Throwable t) { iLoginView.showLoginFailed(ILoginView.ErrCode.WRONG_NET_WORK); }}); }}Copy the code
- In the code above, the constructor LogPresenter holds the Model layer
- Also exposing login(… . , Listener) interface that can be called by the caller
The View layer
View
The layer is responsible for instantiationModel
Layer, andPresenter
Layer binding- Same old, create
BaseFragment<V , P extends IBasePresenter<V>>
The base class
/ * * *@author fishinwater-1999
* @versionThe 2019-11-12 * /
public abstract class BaseFragment<V , P extends IBasePresenter<V>> extends Fragment {
/** * Presenter */
private P mBaseResister;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Automatic binding
if (mBaseResister == null) { mBaseResister = createProsenter(); }}/** * Here determine the type of Presenter to be generated *@return* /
public abstract P createProsenter(a);
/** * Get Presenter *@return* /
public P getPresenter(a) {
if (mBaseResister == null) {
createProsenter();
}
return mBaseResister;
}
/** ** Unbind fragments when they are destroyed */
@Override
public void onStop(a) {
super.onStop();
mBaseResister = null; }}Copy the code
- implementation
View
logic - The View layer is only responsible for user interface responses
/ * * *@author fishinwater-1999
*/
public class LoginFragment extends BaseFragment<ILoginView.LogPresenter> implements ILoginView {
private static final String TAG = "LoginFragment";
private LogViewModel mLogViewModel;
private LoginFragmentBinding binding;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = DataBindingUtil.inflate(inflater, R.layout.login_fragment, container, false);
View view = binding.getRoot();
binding.setLogCallback(getLogActivity());
binding.setFragment(this);
return view;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (mLogViewModel == null) {
mLogViewModel = newLogViewModel(); }}public void login(View v) {
getPresenter().login(
getUserName(),
getUserPwd(),
this);
}
@Override
public LogPresenter createPresenter(a) {
if (mLogViewModel == null) {
mLogViewModel = new LogViewModel();
}
return new LogPresenter(mLogViewModel);
}
@Override
public String getUserName(a) {
return binding.userAccount.getText().toString();
}
@Override
public String getUserPwd(a) {
return binding.userPassword.getText().toString();
}
@Override
public void showLoginSuccess(String response) {
Toast.makeText(getActivity(), "Login successful", Toast.LENGTH_LONG).show();
SharedPreferencesUtil.putString(getActivity(), SharedPreferencesUtil.PRE_NAME_SITUP, SharedPreferencesUtil.USER_ID, response);
ARouter.getInstance().build(RouteUtils.MainActivity).navigation();
getActivity().finish();
}
@Override
public void showLoginFailed(ErrCode errCode) {
if (errCode == ErrCode.WRONG_USER_NAME) {
Toast.makeText(getActivity(), "User name error", Toast.LENGTH_LONG).show();
}else if (errCode == ErrCode.WRONG_USER_PWD){
Toast.makeText(getActivity(), "Password error", Toast.LENGTH_LONG).show();
}else if (errCode == ErrCode.WRONG_NET_WORK) {
Toast.makeText(getActivity(), "Unknown, please check network", Toast.LENGTH_LONG).show(); }}}Copy the code
- Here I use the form of DataBinding to bind the data
- Of course, you can also use a good tripartite library like ButterKnife
- So why did I choose DataBinding? Your own son, you know? / bad smile
run
- So much for sequencing
- For details, you can go directly to the library, the address is at the end of the article
More modulesFIWKeepApp
-
Here I will write the above process in my Demo, address at GitHub you can directly view the repository source, remember to give me a star oh ~ :
-
Demo address: fiwKeepapp-LoginFragment
conclusion
- I think the readers here are right
Retrofit
These are not the only benefits of Retrofit, and there are many more that need to be understood, but this article doesn’t have the space to cover them all - As for the storehouse FIWKeepApp in front of me, I will transform it step by step into the form of Retrofit + OkHttp. Welcome everyone to pay attention to my storehouse and learn about it, and also welcome everyone to give a star
- I’ll do it again later
Android
A variety of knowledge points,Framework
Layer source code, tripartite library for analysis, welcome your attentionThe nuggets of _yuanhaoReceive more quality blog posts in time!