现在正是我们趁热打铁的好时机,赶紧的,板凳放好,瓜子,咖啡自备,小王要撸一发(~~别误会,我说的是撸代码)
有了前面的基础,我们来动手开发一个很小的应用,为啥说他小呢,一个界面就可以了,但是麻雀虽小,五脏俱全。
我们要用到什么知识呢?
1)网络访问 HttpURLConnection(新知识)
2)AsyncTask
3)任务的进度显示
学以致用嘛,学过的东西要用才能成为自己的
4)任务的取消(新知识)
5)接口回调(新知识)
至于为啥不用HttpClient呢,是这样的高版本的android已经不再提供对HttpClient的支持了,另外如果需要用HttpClient需要导入jar包
一个关键点,如果要让我们的应用支持网络访问,必须加上网络的权限 在 清单文件中去加AndroidMenifest.xml中
稍后会说到。
关于上面的东西,如果不会了,可以查询相关资料。这些网络上都有。
第一步:准备材料,下载图片我们总要知道图片的地址吧
以火狐浏览器为例:打开百度图片,右键,选择复制图片地址,OK
第二步:
界面布局设计:
下载前:
下载后:
两个按钮Button:下载,取消
一个视图ImageView 显示下载的图片
一个ProgressBar 显示进度
一个TextView: 用于显示进度的百分比
布局代码:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.cc.myapplication.MainActivity">
<Button
android:id="@+id/btn_download"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onBtnClick"
android:text="下载图片"
/>
<Button
android:id="@+id/btn_cancle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:onClick="onBtnClick"
android:text="取消下载"/>
<ImageView
android:id="@+id/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/btn_download"
android:layout_centerHorizontal="true"
android:adjustViewBounds="true"
android:maxHeight="300dp"
android:maxWidth="300dp"/>
<ProgressBar
android:id="@+id/pro_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/image_view"
android:visibility="visible"
/>
<TextView
android:id="@+id/tv_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="@id/pro_bar"
android:text="进度"
/>
</RelativeLayout>
MainActivity.java
package com.cc.myapplication;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.cc.async.MyAsyncTask;
import com.cc.utils.URLContant;
public class MainActivity extends AppCompatActivity {
private ImageView mImageView;
private ProgressBar mProgressBar;
private TextView mTextView;
private MyAsyncTask mAsyncTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取控件
initView();
}
public void initView(){
mImageView = (ImageView) findViewById(R.id.image_view);
mProgressBar = (ProgressBar) findViewById(R.id.pro_bar);
mTextView = (TextView) findViewById(R.id.tv_progress);
}
public void onBtnClick(View view){
switch (view.getId()){
case R.id.btn_download:
//启动异步任务下载图片
mAsyncTask = new MyAsyncTask(new MyAsyncTask.MyCallback() {
@Override
public void sendImageData(byte[] bytes) {
//doinbackground()执行完成就返回图片
mImageView.setImageBitmap(BitmapFactory.decodeByteArray(bytes,0,bytes.length));
//当下载完毕,就把进度条,和 进度状态显示栏隐藏掉
mProgressBar.setVisibility(View.GONE);
mTextView.setVisibility(View.GONE);
}
@Override
public void sendProgress(Integer... values) {
int current = values[0];
int total = values[1];
//更新进度条
mProgressBar.setProgress(current);
mProgressBar.setMax(total);
//更新进度条状态
mTextView.setText(100*current/total + "%");
}
});
//执行异步任务
mAsyncTask.execute(URLContant.IMAGE_URL);
break;
case R.id.btn_cancle:
//取消下载
//只能取消正在执行的,如果mAsyncTask已执行完毕,或者已经取消掉,都不能再取消
if (mAsyncTask != null){
mAsyncTask.cancel(true);
}
break;
}
}
}
MyAsyncTask主要处理网络下载图片,并通过接口回调的方法,返回结果到MainActivity中 更新 ImageView 和 progressbar TextView
package com.cc.async;
import android.os.AsyncTask;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/**
* Created by My on 2016/7/10.
*/
public class MyAsyncTask extends AsyncTask<String, Integer, byte[]> {
private MyCallback mMyCallback;
public MyAsyncTask(MyCallback mMyCallback){
this.mMyCallback = mMyCallback;
}
@Override
protected void onPreExecute() {
}
@Override
protected byte[] doInBackground(String... params) {
String baseUrl = params[0];
//网络下载
if (baseUrl != null && baseUrl.length() > 0) {
try {
URL url = new URL(baseUrl);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
//如果请求码==200就继续
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
InputStream inputStream = urlConnection.getInputStream();
//使用内存流
ByteArrayOutputStream bStream = new ByteArrayOutputStream();
int len = 0;
//当前下载量
int current = 0;
//通过连接对象调用getContentLength()获取图片的总大小
int total = urlConnection.getContentLength();
byte[] data = new byte[1024];
while ((len = inputStream.read(data)) != -1) {
bStream.write(data, 0, len);
current += len;
//发布进度,每发送一次,onProgressUpdate就会执行一次,也就会把值
//通过接口回调的方式发送给MainActivity,更新UI界面的进度条,进度百分比
publishProgress(current,total);
}
//返回下载的图片内容
return bStream.toByteArray();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
//当doInBackground()方法执行完成后,代表图片已经下载完毕,而 onPostExecute
//中的参数其实就是图片的数据
@Override
protected void onPostExecute(byte[] bytes) {
if (bytes != null && bytes.length > 0){
//下载完成后,向MainActivity返回数据,使用接口回调
mMyCallback.sendImageData(bytes);
}
}
@Override
protected void onProgressUpdate(Integer... values) {
if (values != null && values.length > 0){
//向MainActivity返回数据,使用接口回调
mMyCallback.sendProgress(values);
}
}
//自定义接口,用于不同类之间传递数据
public interface MyCallback{
//发送数据,谁实现,谁获取
void sendImageData(byte[] bytes);
void sendProgress(Integer... values);
}
}
最后最最重要的是别忘了,加网络权限:
<uses-permission android:name="android.permission.INTERNET"/>