今天我們來談談OkHttp3這個讓人遺忘的網路框架,在Volley和Retrofit的強勢登場,OkHttp3相對的讓人提不起興趣。畢竟如果要使用OkHttp3就要對它進行再封裝,但是這對於很多新人來說是有點困難的,他們更願意去使用Retrofit。Anyway,我們先不談論這三個框架的優勝劣汰,我們就單純地講解一下OkHttp3的簡單運用。
首先我們先建立一個OkHttp3Demo的專案,開啟AS,File——New——New project,建立名為OkHttp3Demo的專案。然後開啟網頁OKHttp3的連結,你可以選擇下載GIt專案匯入,也可以找到下面的這麼一句程式碼複製單引號裡面的內容:
testImplementation 'com.squareup.okhttp3:mockwebserver:3.1
然後回到AS裡,在建立的專案裡的Model的build.gredle裡面加上這麼一行程式碼:
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:26.+' compile 'com.android.support.constraint:constraint-layout:1.0.2' compile 'com.squareup.okhttp3:mockwebserver:3.10.0'//匯入OkHttp3}
這樣我們的OkHttp3就匯入到我們的專案裡面了,接下來我們在activity_main.xml中加上一個按鈕,程式碼如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.a28062.okhttp3demo.MainActivity"> <Button android:onClick="getRequest" android:text="GET Button" android:id="@+id/get_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
再然後我們開啟MainActivity類,因為我在建立Button的時候就指定了響應方法getRequest,所以我們在這個主類中實現它的響應方法就行了。在這個方法中我們建立一個OkHttpClient的物件,這個物件我們可以把它理解為一個PC端或者一部手機,因為我們開啟網頁就是依靠PC或者手機的瀏覽器。
我們以透過OkHttp3的GET請求百度網頁為例,建立一個String型別的URL來儲存連結:http://www.baidu.com 。再建立一個Request物件把URL傳遞進來封裝好。之後呼叫OkHttpClient物件的newCall().enqueue()方法,把Request請求放入newCall方法中,在enqueue方法中建立一個匿名的CallBack物件,重寫Callback物件中的onFailure方法和onResponse方法,當請求成功時會呼叫onResponse方法,反之呼叫onFailure方法。這是一個非同步請求,當然你也可以試一下同步請求,使用newCall().execute()方法。不過耗時任務都不在主執行緒中執行,可能會導致程式崩潰。上程式碼:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void getRequest(View v){ OkHttpClient client = new OkHttpClient(); String URL = "http://www.baidu.com"; Request request = new Request.Builder().url(URL).build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Log.d("This is a test","失敗:"+e.getLocalizedMessage());//當請求失敗的時候我們執行onFailure方法 } @Override public void onResponse(Call call, Response response) throws IOException { Log.d("This is a test","成功:" +response.body().string());//當請求成功的時候我們執行onResponse方法 } }); }}
說完Get請求,讓我們來了解一下Post請求。OkHttp3的Post請求分為表單引數形式和Json引數形式,那麼最經典的案例就是關於登陸功能的實現。現在我們試著做這樣一個功能,當客戶填寫完賬號密碼點選提交的時候,我們透過OkHttp3的Post請求,從控制元件中獲取客戶填寫的資訊傳送到後端,再由後端的靜態類中校驗。如果賬號密碼都校驗成功就返回一個message和一個success的狀態碼,然後我們再回到主執行緒中吐司這個message(為什麼回到主執行緒?)。大概功能就是這樣,關於接受資料的後端我相信對於聰明的你們來說應該不難我就不細說了。
我們新建一個名為OkHttp3PostDemo的專案,開啟AS選擇File——new——newproject建立一個新的專案,然後匯入OkHttp3依賴包,這次我們再加入一個butterknife的依賴包,在App裡的Build.gradle加上下面的程式碼:
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:26.+' compile 'com.android.support.constraint:constraint-layout:1.0.2' compile 'com.jakewharton:butterknife:8.8.1' compile 'com.jakewharton:butterknife-compiler:8.8.1' compile 'com.squareup.okhttp3:mockwebserver:3.10.0'}
然後再在gradle裡的Build.gradle加上如下程式碼:
dependencies { classpath 'com.android.tools.build:gradle:2.3.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files classpath 'com.jakewharton:butterknife-gradle-plugin:8.8.1' }
接下來我們設計一下activity_main.xml,程式碼如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:orientation="vertical" android:layout_height="match_parent" android:layout_margin="5dp" tools:context="com.example.a28062.okhttp3postdemo.MainActivity"> <EditText android:maxLines="1" android:hint="使用者名稱稱:" android:id="@+id/user_name" android:layout_width="match_parent" android:layout_height="wrap_content" /> <EditText android:password="true" android:maxLines="1" android:hint="使用者密碼:" android:id="@+id/pass_world" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:text="提交" android:id="@+id/sommint" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
接下來我們開啟MainActivity類,找到setContentView,右擊裡面的佈局檔案,選擇Generate,再選擇Generated ButterKnife injection,然後勾選所有的控制元件再在Button這個控制元件上勾選Onclick方法,點選確認。接下來我們在生成的Onclick方法中呼叫方法loginWithFrom,當然這是一個我們自己定義的方法主要是用來處理耗時任務的邏輯,我們的OkHttp3的邏輯就寫在這裡,傳入兩個引數分別為username和passworld。
在loginWithFrom方法中我們首先建立一個okHttpClient物件,然後建立一個字串URL用來存放要訪問的地址,這裡我選擇了建立一個Constant的類再用裡面的靜態變數來存放訪問地址,這樣做的好處是到時可以複用並且減少程式碼。接下來就是Post請求中比較重要的,新建一個RequestBody物件,簡單的理解為請求以什麼形式提交,然後new一個RequestBody,發現New不出來。別緊張我們點進去看一下原始碼就會發現這個類是個抽象類所以肯定不能建立例項物件,但是它肯定有子類,我們右擊抽象類選擇GO TO,再選擇Implementation就能看到它有兩個子類。第一個FormBody字面意思,表單形式提交請求,第二個是多種形式。我們毫無疑問地選擇第一個,回到主類,new一個FormBody.Builder()物件然後新增表單資訊就可以了。其他的內容和Get方法一樣,最重要的就是這個RequestBody的組建。上程式碼:
public class MainActivity extends AppCompatActivity { @BindView(R.id.user_name) EditText userName; @BindView(R.id.pass_world) EditText passWorld; @BindView(R.id.sommint) Button sommint; OkHttpClient okHttpClient; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); } @OnClick(R.id.sommint) public void onViewClicked() { String username = userName.getText().toString().trim();//獲取控制元件內容 String passworld = passWorld.getText().toString().trim(); loginWithFrom(username,passworld);//呼叫請求方法方法 } private void loginWithFrom(String username,String passworld){ okHttpClient = new OkHttpClient(); String URL = Constant.API.BASE_URL;//在靜態類其中取出BASE_URL的訪問地址 RequestBody body = new FormBody.Builder().add("username",username).add("passworld",passworld).build();//例項化RequestBody final Request request =new Request.Builder() .post(body)//新增Post請求 .url(URL) .build(); okHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Log.d("MainActivity","伺服器開小差了"); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()){//判斷服務端是否響應成功 String json = response.body().string();//把返回的資訊儲存起來 try { JSONObject jsonObject = new JSONObject(json);//透過Json格式去獲取返回的相應資訊 String message = jsonObject.optString("message"); int success = jsonObject.optInt("success"); runOnUiThread(new Runnable() {//返回主執行緒更新UI @Override public void run() { if (success == 1){ Toast.makeText(MainActivity.this,"登陸成功",Toast.LENGTH_SHORT).show(); }else { Toast.makeText(MainActivity.this,message,Toast.LENGTH_SHORT).show(); } } }); } catch (JSONException e) { e.printStackTrace(); } } } }); } }
接下來我們來了解一下Json引數形式的Post請求,大致上都是一樣的,我們只需要改變的是RequestBody,之前我們用的是FormBody來構建表單的請求。現在我們使用Request.create()的方法來建立Json形式的請求, 還記得我們上面說的RequestBody這個抽象類的第二個子類麼?我們這次就是使用它來進行提交Json形式的請求,在create裡面填入MediaType.parse()方法。這個方法其實就是要我們選擇一種提交形式,開啟它的原始碼就能看見提交Json資料的格式的示範,我們填入Application/json,這樣我們就選擇了Json的引數形式。create方法還有個引數,我們填入我們的Json資料就可以了。
那麼Json資料怎麼儲存呢?我們可以建立一個Json物件,然後使用Put方法把資料用鍵值對的方式一個一個地存放進去,注意這裡的資料一定不能錯,不然伺服器會檢測不了。上個程式碼圖:
public class MainActivity extends AppCompatActivity { @BindView(R.id.user_name) EditText userName; @BindView(R.id.pass_world) EditText passWorld; @BindView(R.id.sommint) Button sommint; OkHttpClient okHttpClient; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); } @OnClick(R.id.sommint) public void onViewClicked() { String username = userName.getText().toString().trim(); String passworld = passWorld.getText().toString().trim(); loginWithJson(username,passworld); } private void loginWithJson(String username, String passworld) { okHttpClient = new OkHttpClient(); String URL = Constant.API.BASE_URL; JSONObject obj = new JSONObject();//建立一個Json物件來存放資料 try { obj.put("username",username);//使用PUT方法來存放資料 obj.put("passworld",passworld); } catch (JSONException e) { e.printStackTrace(); } String jsonParams = obj.toString();//將Json格式轉化為字串 RequestBody body = RequestBody.create(MediaType.parse("Application/json"),jsonParams);//透過抽象類中的子類來構建多種形式的提交方式 Request request =new Request.Builder() .post(body) .url(URL) .build(); okHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Log.d("MainActivity","伺服器開小差了"); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()){ String json = response.body().string(); try { JSONObject jsonObject = new JSONObject(json); final String message = jsonObject.optString("message"); final int success = jsonObject.optInt("success"); runOnUiThread(new Runnable() { @Override public void run() { if (success == 1){ Toast.makeText(MainActivity.this,"登陸成功",Toast.LENGTH_SHORT).show(); }else { Toast.makeText(MainActivity.this,message,Toast.LENGTH_SHORT).show(); } } }); } catch (JSONException e) { e.printStackTrace(); } } } }); }}
這樣我們的OkHttp3的簡單運用就講完了,之後我可能還會寫一些關於封裝OkHttp3的文章,到時請大家務必過來看看,一起探討一下。手打不易哈,轉載的小夥伴請標明