来自慕课网
使用okhttp的第一步就是应该在自己工程的module/build.gradle中引入支持库,如下所示:
implementation 'com.squareup.okhttp3:okhttp:3.9.1'
okhttp的使用分为同步和异步,同步需要在子线程中使用,而异步不需要;okhttp一般的使用请求方式有get请求和post请求,get请求一般用来向服务器获取数据,pos请求用来向服务器提交数据。post请求方式用来postString,postFile,upload,get请求方式用来download,downloadImage等操作,下面是具体的操作实现栗子
一 、 get方式用来进行模拟登录,将服务器返回的结果设置到textview上
public class SecondActivity extends AppCompatActivity { private static final String TAG = "SecondActivity"; private Button doGetButton; private TextView mResultTextView; private String mBaseUrl = "http://169.254.66.218:8080/okhttp/"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); doGetButton = (Button) findViewById(R.id.btu_doGet); mResultTextView = (TextView) findViewById(R.id.tv_result); doGetButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { doGet(); } }); } private void doGet(){ OkHttpClient okHttpClient = new OkHttpClient(); //1、拿到OkHttpClient对象 //2.构造Request Request.Builder builder = new Request.Builder(); Request request = builder .get() .url(mBaseUrl + "login?username=hyman&password=1234") .build(); //3.将Request封装为call Call call = okHttpClient.newCall(request); //4.执行call // 同步方式 Response reaponse = call.execute(); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Log.e(TAG, "onFailure: " + e.getMessage()); e.printStackTrace(); } @Override public void onResponse(Call call, Response response) throws IOException { Log.e(TAG, "onResponse: " + response); final String res = response.body().string(); Log.e(TAG, "onResponse: " + res); runOnUiThread(new Runnable() { @Override public void run() { mResultTextView.setText(res); } }); } }); } }二、 post方式用来进行模拟登录,将服务器返回的结果设置到textview上
public class SecondActivity extends AppCompatActivity { private static final String TAG = "SecondActivity"; private Button doPostButton; private TextView mResultTextView; private String mBaseUrl = "http://169.254.66.218:8080/okhttp/"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); doPostButton = (Button) findViewById(R.id.btu_doPost); mResultTextView = (TextView) findViewById(R.id.tv_result); doPostButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { doGet(); } }); } private void doGet(){ //1、拿到OkHttpClient对象 OkHttpClient okHttpClient = new OkHttpClient(); //2.构造RequestBody RequestBody requestBody = new FormBody.Builder() .add("username", "admin") .add("password", "123") .build(); //2.1构造Request Request request = new Request.Builder() .url(mBaseUrl + "login") .post(requestBody) .build(); //3.将Request封装为call Call call = okHttpClient.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Log.e(TAG, "onFailure: " + e.getMessage()); e.printStackTrace(); } @Override public void onResponse(Call call, Response response) throws IOException { Log.e(TAG, "onResponse: " + response); final String res = response.body().string(); Log.e(TAG, "onResponse: " + res); runOnUiThread(new Runnable() { @Override public void run() { mResultTextView.setText(res); } }); } }); } }三、 post方式向服务器提交字符串
private void doPostString() { //1、拿到OkHttpClient对象 //2.构造RequestBody RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain;charset=utf-8"), "{username:hyman,password:123}"); //2.1构造Request Request request = new Request.Builder() .url(mBaseUrl + "postString") .post(requestBody) .build(); //3.将Request封装为call Call call = okHttpClient.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Log.e(TAG, "onFailure: " + e.getMessage()); e.printStackTrace(); } @Override public void onResponse(Call call, Response response) throws IOException { Log.e(TAG, "onResponse: " + response); final String res = response.body().string(); Log.e(TAG, "onResponse: " + res); runOnUiThread(new Runnable() { @Override public void run() { mResultTextView.setText(res); } }); } }); }四、 post方式向服务器提交文件,其中image.jpg是在sd卡存储目录中放置好的一张图片
private void doPostFile() { //1、拿到OkHttpClient对象 //File sdCard = Environment.getExternalStorageDirectory(); File file = new File(Environment.getExternalStorageDirectory(), "image.jpg"); if (!file.exists()) { Log.e(TAG, "run: " + file.getAbsolutePath() + "not exists!"); } //2.构造RequestBody //mime type RequestBody requestBody = RequestBody.create(MediaType.parse("application/octet-stream"), file); //2.1构造Request Request request = new Request.Builder() .url(mBaseUrl + "postFile") .post(requestBody) .build(); //3.将Request封装为call Call call = okHttpClient.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Log.e(TAG, "onFailure: " + e.getMessage()); e.printStackTrace(); } @Override public void onResponse(Call call, Response response) throws IOException { Log.e(TAG, "onResponse: " + response); final String res = response.body().string(); Log.e(TAG, "onResponse: " + res); runOnUiThread(new Runnable() { @Override public void run() { mResultTextView.setText(res); } }); } }); }五、post方式上传文件,上传文件涉及一个客户端文件上传的进度问题,通过继承RequestBody自己实现方法回调
//上传文件 private void doUpload() { //1、拿到OkHttpClient对象 //File sdCard = Environment.getExternalStorageDirectory(); File file = new File(Environment.getExternalStorageDirectory(), "image.jpg"); if (!file.exists()) { Log.e(TAG, "run: " + file.getAbsolutePath() + "not exists!"); } RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM) .addFormDataPart("username", "hyman") .addFormDataPart("password", "12345") .addFormDataPart("mPhoto", "hyman.jpg", RequestBody.create(MediaType.parse("application/octet-stream"), file)).build(); //上传文件的进度条问题 CountingRequestBody countingRequestBody = new CountingRequestBody(body, new CountingRequestBody.Listener() { @Override public void onRequestProgress(long bytesWritten, long contentLength) { Log.e(TAG, bytesWritten + " / " + contentLength); } }); //2.构造RequestBody //mime type // RequestBody requestBody = RequestBody.create(MediaType.parse("application/octet-stream"), file); //2.1构造Request Request request = new Request.Builder() .url(mBaseUrl + "uploadInfo") .post(countingRequestBody) .build(); //3.将Request封装为call Call call = okHttpClient.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Log.e(TAG, "onFailure: " + e.getMessage()); e.printStackTrace(); } @Override public void onResponse(Call call, Response response) throws IOException { Log.e(TAG, "onResponse: " + response); final String res = response.body().string(); Log.e(TAG, "onResponse: " + res); runOnUiThread(new Runnable() { @Override public void run() { mResultTextView.setText(res); } }); } }); }CountingRequestBody的内容为
public class CountingRequestBody extends RequestBody { protected RequestBody delegate; private Listener listener; private CountingSink mCountingSink; public CountingRequestBody(RequestBody delegate, Listener listener){ this.delegate = delegate; this.listener = listener; } @Nullable @Override public MediaType contentType() { return delegate.contentType(); } @Override public long contentLength() throws IOException { return delegate.contentLength(); } @Override public void writeTo(BufferedSink sink) throws IOException { mCountingSink = new CountingSink(sink); BufferedSink bufferedSink = Okio.buffer(mCountingSink); delegate.writeTo(bufferedSink); bufferedSink.flush();//刷新 } protected final class CountingSink extends ForwardingSink{ private long bytesWritten; public CountingSink(Sink delegate){ super(delegate); } @Override public void write(Buffer source, long byteCount) throws IOException { super.write(source, byteCount); bytesWritten += byteCount; listener.onRequestProgress(bytesWritten,contentLength()); } } public static interface Listener{ //已写入的字节数---总共的字节数 void onRequestProgress(long bytesWritten,long contentLength); } }六、get方式下载文件,其中files/hyman.jpg是在服务器端存在的一张图片文件,是在tomcat/webapps/okhttp/新建的files文件夹下的hyman.jpg,即第五种情况下上传好的图片文件
//下载文件 private void doDownload() { //1、拿到OkHttpClient对象 //2.构造Request Request.Builder builder = new Request.Builder(); Request request = builder .get() .url(mBaseUrl + "files/hyman.jpg") .build(); //3.将Request封装为call Call call = okHttpClient.newCall(request); //4.执行call call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Log.e(TAG, "onFailure: " + e.getMessage()); e.printStackTrace(); } @Override public void onResponse(Call call, Response response) throws IOException { Log.e(TAG, "onResponse: "); //下载进度问题 final long total = response.body().contentLength(); long sum = 0L; InputStream is = response.body().byteStream(); int len = 0; File file = new File(Environment.getExternalStorageDirectory(), "hyman_xiazai.jpg"); FileOutputStream fos = new FileOutputStream(file); byte[] buf = new byte[128]; while ((len = is.read(buf)) != -1) { fos.write(buf, 0, len); sum += len; Log.e(TAG, sum + " / " + total); final long finalSum = sum; runOnUiThread(new Runnable() { @Override public void run() { mResultTextView.setText(finalSum + " / " + total); } }); } fos.flush(); fos.close(); is.close(); Log.e(TAG, "onResponse: download success"); } }); }七、get方式下载图片 下载图片涉及图片的一个大小尺寸适配问题,应该根据合适的方式进行缩放等
//下载图片 public void doDownloadImage(View view) { //1、拿到OkHttpClient对象 //2.构造Request Request.Builder builder = new Request.Builder(); Request request = builder .get() .url(mBaseUrl + "files/hyman.jpg") .build(); //3.将Request封装为call Call call = okHttpClient.newCall(request); //4.执行call call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Log.e(TAG, "onFailure: " + e.getMessage()); e.printStackTrace(); } @Override public void onResponse(Call call, Response response) throws IOException { Log.e(TAG, "onResponse: "); InputStream is = response.body().byteStream(); final Bitmap bitmap = BitmapFactory.decodeStream(is); Log.e(TAG, "onResponse: bitmap is width:" + bitmap.getWidth() + " bitmap is height:" + bitmap.getHeight()); runOnUiThread(new Runnable() { @Override public void run() { mResultImageView.setImageBitmap(bitmap); } }); } }); }