在android项目的开发过程中网络请求是非常常用的。这里简单介绍两种方法
在android中无论使用哪种方法发起网络请求,都需要先声明网络权限
1 2 3 4 5 6
| <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.example.moshuying"> <uses-permission android:name="android.permission.INTERNET" /> </manifest>
|
http请求
通常在android项目中会使用两种(也有可能基于这两种进行封装)请求方式,HttpURLConnection是google较为推荐的一种。okhttp也不错,往往能正确获取到页面数据。
HttpURLConnection
作为官方推荐的一种请求方法,自然是不需要引入的啦~
非常简单直接上代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| public class MainActivity extends AppCompatActivity {
private TextView textView;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
findViewById(R.id.send_request).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { send(); } });
textView = (TextView) findViewById(R.id.response_data); }
private void send() { new Thread(new Runnable() { @Override public void run() { HttpURLConnection connection = null; BufferedReader reader = null; try { URL url = new URL("http://www.163.com"); connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setConnectTimeout(5000); connection.setReadTimeout(5000);
InputStream in = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(in)); StringBuilder result = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { result.append(line); } show(result.toString()); } catch (MalformedURLException e) { e.printStackTrace(); } catch (ProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } if (connection != null) { connection.disconnect(); } } } }).start(); }
private void show(final String result) { runOnUiThread(new Runnable() { @Override public void run() { textView.setText(result); } }); } }
|
因为在 Android 中不允许在子线程中执行 UI 操作(当然不光是Android,python js(worker)都不允许在子线程执行ui操作),所以我们通过 runOnUiThread 方法,切换为主线程,然后再更新 UI 元素。
关于不能在子线程执行UI操作的主要原因是线程安全,实际上并不是禁止在子线程中执行 UI 操作而是禁止在非UI线程执行UI 操作。
绝大部分 GUI 系统都是只允许「单个线程对某块区域做绘制操作的」,例如在 Windows 和 Android 系统下都把这块区域叫做 Window。如果允许多个线程对同一块区域做绘制的话,很有可能导致某个线程还没绘制完,另一个线程上一些依赖之前绘制结果的操作出问题,例如 Alpha 混合。除非加锁,然而加锁更慢还不如单线程。[ 1]nekocode.Android[ DB].知乎,https://www.zhihu.com/question/24764972/answer/272848960
okhttp
OKHttp 是一个处理网络请求的开源项目,目前是 Android 最火热的轻量级框架,由移动支付 Square 公司贡献(该公司还贡献了Picasso)。希望替代 HttpUrlConnection 和 Apache HttpClient。[ 2]deniro.说说在 Android 中如何发送 HTTP 请求[ DB].简书,https://www.jianshu.com/p/5eee1ef02700
这个库不是内置的,需要先引入依赖,最新版本和具体文档在OkHttp中获取。然后在项目目录下的build.gradle(Module:app)
文件中更新依赖,看清楚文件名别弄错了
我这里用的是android 10.0+ 所以没有compile
变成了implementation
1 2 3
| dependencies { implementation 'com.squareup.okhttp3:okhttp:4.9.0' }
|
然后记得点击右上角的Sync now
把依赖文件同步后真正加进来
这里简单做了一个get请求和一个post请求的示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| class HttpGetRequest implements Callable<String> { public String url = null; @Override public String call() { String returnValue = null; OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder().url(url).build(); Response response = null; try { response = client.newCall(request).execute(); returnValue = response.body().string(); } catch (IOException e) { e.printStackTrace(); } return returnValue; } }
class HttpPostRequest implements Callable<String>{ public String url = null; public String json = null; public static final MediaType JSON = MediaType.get("application/json; charset=utf-8"); @Override public String call(){ String returnValue = null; OkHttpClient client = new OkHttpClient(); RequestBody body = RequestBody.create(json, JSON); Request request = new Request.Builder().url(url).post(body).build(); Response response = null; try { response = client.newCall(request).execute(); returnValue = response.body().string(); } catch (IOException e) { e.printStackTrace(); } return returnValue; } }
|
考虑到使用时需要用到多线程操作,为了避免因为请求时间造成的界面卡顿,这里用了Callable
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public static String sendByOKHttp() { ExecutorService executorService = Executors.newCachedThreadPool(); HttpGetRequest httpGetRequest = new HttpGetRequest(); httpGetRequest.url = "https://exampleapp.moshuying.top/node_api/product_list"; Future<String> submit = executorService.submit(httpGetRequest); String data = ""; try { data = submit.get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } System.out.println(data); LinkedHashMap<String,String> jsonMap = JSON.parseObject(data,new TypeReference<LinkedHashMap<String, String>>(){}); return jsonMap.get("data"); }
|
参考文章:
说说在 Android 中如何发送 HTTP 请求
OkHttp