Android入門之使用OKHttp組件訪問網(wǎng)絡(luò)資源
簡介
今天的課程開始進入高級課程類了,我們要開始接觸網(wǎng)絡(luò)協(xié)議、設(shè)備等領(lǐng)域編程了。在今天的課程里我們會使用OKHttp組件來訪問網(wǎng)絡(luò)資源而不是使用Android自帶的URLConnection。一個是OKHttp組件更方便二個是OKHttp組件本身就帶有異步回調(diào)功能。
下面就進入課程。
課程目標



我們的課程目標有4個點:
- 使用OKHttp組件;
- 使用OKHttp組件加載網(wǎng)絡(luò)圖片顯示在APP的ImgView里;
- 使用OKHttp組件加載給定網(wǎng)頁代碼顯示在ScrollView里;
- 使用OKHttp組件加載給定網(wǎng)頁顯示在WebView里;
以上過程都為異步加載。
代碼前在gradle里要先聲明對于OKHttp組件的引用
要使用OKHttp組件,我們必須要在build.gradle中加入以下語句:
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
以下是加完上述語句后的build.gradle。

訪問網(wǎng)絡(luò)資源需要給到APP以權(quán)限
我們因為要訪問網(wǎng)絡(luò)資源,因此我們需要給到APP以相應(yīng)的權(quán)限。編輯AndroidManifest.xml文件,并加入以下兩行聲明。
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
加完后的AndroidManifest.xml長這樣

代碼
菜單res\menu\pop_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menuItemDisplayPic" android:title="加載圖片" />
<item android:id="@+id/menuItemDisplayHtmlCode" android:title="加載網(wǎng)頁代碼" />
<item android:id="@+id/menuItemDisplayHtmlPage" android:title="加載網(wǎng)頁" />
</menu>主UI界面
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/buttonShowMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/textColor"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:text="展示彈出菜單" />
<ImageView
android:id="@+id/imgPic"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
<ScrollView
android:id="@+id/scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone">
<TextView
android:id="@+id/htmlTxt"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</ScrollView>
<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>MainActivity
package org.mk.android.demo.http;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.PopupMenu;
import android.widget.ScrollView;
import android.widget.TextView;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import okhttp3.OkHttpClient;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
public class MainActivity extends AppCompatActivity {
private String TAG = "DemoOkHttp";
private Button buttonShowMenu;
private TextView htmlTxt;
private ImageView imgPic;
private WebView webView;
private ScrollView scroll;
private Bitmap bitmap;
private String htmlContents;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonShowMenu = (Button) findViewById(R.id.buttonShowMenu);
htmlTxt = (TextView) findViewById(R.id.htmlTxt);
imgPic = (ImageView) findViewById(R.id.imgPic);
webView = (WebView) findViewById(R.id.webView);
scroll = (ScrollView) findViewById(R.id.scroll);
buttonShowMenu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
PopupMenu popup = new PopupMenu(MainActivity.this, buttonShowMenu);
popup.getMenuInflater().inflate(R.menu.pop_menu, popup.getMenu());
popup.setOnMenuItemClickListener(new MenuItemClick());
popup.show();
}
});
}
// 定義一個隱藏所有控件的方法:
private void hideAllWidget() {
imgPic.setVisibility(View.GONE);
scroll.setVisibility(View.GONE);
webView.setVisibility(View.GONE);
}
private class MenuItemClick implements PopupMenu.OnMenuItemClickListener {
@Override
public boolean onMenuItemClick(MenuItem item) {
String imgPath = "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.alicdn.com%2Fi2%2F2542318073%2FO1CN01fJvTi029VTwR16EvP_%21%212542318073.jpg&refer=http%3A%2F%2Fimg.alicdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1673938156&t=69e5ee87fbf4b81b5f6eea53ed5b5158";
String htmlPagePath = "https://www.baidu.com";
switch (item.getItemId()) {
case R.id.menuItemDisplayPic:
downLoadImgFromPath(imgPath);
break;
case R.id.menuItemDisplayHtmlCode:
getHtmlAsync(htmlPagePath, 102);
break;
case R.id.menuItemDisplayHtmlPage:
getHtmlAsync(htmlPagePath, 103);
break;
}
return true;
}
}
private Handler httpHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message msg) {
Log.i(TAG, ">>>>>>receive handler Message msg.what is: " + msg.what);
switch (msg.what) {
case 101:
hideAllWidget();
imgPic.setVisibility(View.VISIBLE);
Log.i(TAG, "begin to show img from bitmap type's data");
imgPic.setImageBitmap(bitmap);
break;
case 102:
hideAllWidget();
Log.i(TAG, "begin to show html contents");
scroll.setVisibility(View.VISIBLE);
Log.d(TAG, ">>>>>>htmlContents->\n" + htmlContents);
htmlTxt.setText(htmlContents);
break;
case 103:
hideAllWidget();
Log.i(TAG, "begin to show html page in webview");
webView.setVisibility(View.VISIBLE);
Log.d(TAG, ">>>>>>htmlContents->\n" + htmlContents);
webView.loadDataWithBaseURL("", htmlContents, "text/html", "UTF-8", "");
break;
}
return false;
}
});
/**
* 使用okhttp 異步下載圖片
*/
private void downLoadImgFromPath(String path) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(path)
.build();
Log.i(TAG, ">>>>>>into doanloadImgFromPath method");
try {
Call call = client.newCall(request); // 使用client去請求
call.enqueue(new Callback() { // 回調(diào)方法,>>> 可以獲得請求結(jié)果信息
InputStream inputStream = null;
@Override
public void onFailure(Call call, IOException e) {
Log.e(TAG, ">>>>>>下載失敗", e);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.i(TAG, ">>>>>>into onResponse method");
try {
inputStream = response.body().byteStream();
Log.i(TAG, ">>>>>>the response code is: " + response.code());
if (200 == response.code()) {
bitmap = BitmapFactory.decodeStream(inputStream);
Log.i(TAG, ">>>>>>sendEmptyMessage 101 to handler");
httpHandler.sendEmptyMessage(101);
} else {
Log.i(TAG, ">>>>>>下載失敗");
}
} catch (Exception e) {
Log.e(TAG, ">>>>>>okHttp onResponse error: " + e.getMessage(), e);
} finally {
try {
inputStream.close();
} catch (Exception e) {
}
}
}
});
} catch (Exception e) {
Log.e(TAG, ">>>>>>OkHttp調(diào)用失敗", e);
}
}
//異步不需要創(chuàng)建線程
private void getHtmlAsync(String path, int handlerCode) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(path).build();
//請求的call對象
Call call = client.newCall(request);
//異步請求
call.enqueue(new Callback() {
//失敗的請求
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
Log.e(TAG, ">>>>>>加載path失敗", e);
}
//結(jié)束的回調(diào)
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
//響應(yīng)碼可能是404也可能是200都會走這個方法
Log.i(TAG, ">>>>>>the response code is: " + response.code());
if (200 == response.code()) {
try {
ResponseBody responseBody = response.body();
BufferedSource source = responseBody.source();
source.request(Long.MAX_VALUE);
Buffer buffer = source.buffer();
Charset UTF8 = Charset.forName("UTF-8");
htmlContents = buffer.clone().readString(UTF8);
Log.i(TAG, ">>>>>>sendEmptyMessage " + handlerCode + " to handler");
httpHandler.sendEmptyMessage(handlerCode);
Log.i(TAG, "getAsyncHtmlGet成功");
} catch (Exception e) {
Log.e(TAG, ">>>>>>read htmlPage error: " + e.getMessage(), e);
}
}
}
});
}
}核心代碼導(dǎo)讀
我們使用的是
Call call = client.newCall(request);
它本身就是支持異步的一個調(diào)用。 然后在得到相應(yīng)的Http報文后使用一個Handler向APP主界面發(fā)起改變界面中內(nèi)容的調(diào)用。
這邊有一點需要注意的是OKHttp在返回的response.body()這個API,在一次請求里只能被使用一次。即如果你已經(jīng)有以下一句類似的調(diào)用:
inputStream = response.body().byteStream();
你就不能再在它以下的語句中調(diào)用一次response.body()了。
自己動一下手試試看效果吧。
到此這篇關(guān)于Android入門之使用OKHttp組件訪問網(wǎng)絡(luò)資源的文章就介紹到這了,更多相關(guān)Android OKHttp訪問網(wǎng)絡(luò)資源內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android MPAndroidChart開源圖表庫之餅狀圖的代碼
MPAndroidChart是一款基于Android的開源圖表庫,MPAndroidChart不僅可以在Android設(shè)備上繪制各種統(tǒng)計圖表,而且可以對圖表進行拖動和縮放操作,應(yīng)用起來非常靈活2018-05-05
Android Gradle多渠道打包的實現(xiàn)方法
這篇文章主要介紹了Android Gradle多渠道打包的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
Android 利用反射+try catch實現(xiàn)sdk按需引入依賴庫的方法
這篇文章主要介紹了Android 利用反射+try catch來實現(xiàn)sdk按需引入依賴庫,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-11-11
Android開發(fā)使用Activity嵌套多個Fragment實現(xiàn)橫豎屏切換功能的方法
這篇文章主要介紹了Android開發(fā)使用Activity嵌套多個Fragment實現(xiàn)橫豎屏切換功能的方法,結(jié)合實例形式分析了Android使用Activity嵌套多個Fragment進行橫豎屏切換的原理與具體操作技巧,需要的朋友可以參考下2017-11-11
Android中Fragment的分屏顯示處理橫豎屏顯示的實現(xiàn)方法
今天小編就為大家分享一篇關(guān)于Android中Fragment的分屏顯示處理橫豎屏顯示的實現(xiàn)方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-03-03
Android?Studio實現(xiàn)簡單頁面跳轉(zhuǎn)的詳細教程
這篇文章主要給大家介紹了關(guān)于Android?Studio實現(xiàn)簡單頁面跳轉(zhuǎn)的詳細教程,文中通過圖文介紹的非常詳細,對大家學(xué)習(xí)或者使用Android?Studio具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2023-01-01

