Android 图片异步加载,延时加载的一些思路

来源:互联网 发布:2016年淘宝刷单有用吗 编辑:程序博客网 时间:2024/05/22 03:15
  

写在前面:此博文为概念性、思路方面的阐述,并无太多可参考的代码。

我们通常会遇到这样一个情况,有一张图片保存在不确定的服务端,我们需要下载图片并显示。按照这样一个思路来写Android程序:假如我们已经写好了一个确定可以在java的编译器中编译运行的函数 DownImage(),此函数返回的是一个Bitmap对象,如果我们在Activity的Oncreat函数中加入此函数,并将返回丢给一个ImageView的话,多半情况我们什么都得不到或者是直接得到了一个系统错误。这里就要提到Android的一种机制或者说是,即“非常耗时”且执行过程不可预测的方法不能在主线程中运行。也许读者看到这里会抱怨:“靠,这么坑爹啊!!”。但是请注意分析这样一个过程,当程序正在初始化的时候,你居然让主线程等着你“吃个早点”再做事,那无疑会让程序的稳定性、可靠性都出很大的问题。

所以,言归正传,我们需要异步加载,我们需要一个合理的方法来加载那些并非触手可及的东西。一种常见的方法是,在主线程中新建一个线程,让这个线程去下载图片,并把结果反馈回来。关于如何反馈结果,又有两种方法,一种是使用Handler来通信,你可以将结果封装在一个Bundle对象中,然后在msg中附加Bundle发送给主线程的“特定”Handler处理。对于这种方法一种简单的模型如下:

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
package com.example.test;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.view.Menu;
public class TestAc extends Activity {
    public static Handler myhandler;
    @SuppressLint("HandlerLeak")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);
        myhandler=new Handler(){
            @Override
            public void handleMessage(Message msg) {
                msg.getData().getString("Msg");
            }
        };
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.test, menu);
        return true;
    }
     class MyThread implements Runnable{
        @Override
        public void run() {
            // TODO 自动生成的方法存根
            Message msg=new Message();
            Bundle b=new Bundle();
            b.putString("Msg""这是一个子线程发来的消息");
            msg.setData(b);
            TestAc.myhandler.sendMessage(msg);
        }}
}


另外的一种方法是通过系统广播来实现,根据不同的应用需求,朋友们可以选择不同的方式来实现。

写到这里,也才算是写完前沿,因为到现在我还没有开始讨论异步的一些实现原理和方法:

通常来看,如果我们使用ListView、GridView、甚至是ViewPager来动态加载数据的时候,我们的数据在网络中,下载数据的过程很缓慢,以至于我们不太愿意在程序运行的头几分钟让用户干等着。所以,一种比较合适的方法是用上面的方法来动态加载数据。对于ListView或者GridView来说,我们可以对他们的Adapter进行一下的操作:

假如有一个Adapter的名字叫做MyAdapter,通常我们在创建Adapter的时候会给他一个数据源。这个数据如果后面我们不动他,他就是固定的,死的,希望朋友们注意我的这句提示。假如有个Adatper的例子如下:

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
package com.example.test;
import java.util.List;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
public class MyAdapter extends BaseAdapter{
    private List<?> mlist;
    @Override
    public int getCount() {
        // TODO 自动生成的方法存根
        return mlist.size();
    }
    @Override
    public Object getItem(int position) {
        // TODO 自动生成的方法存根
        return mlist.get(position);
    }
    @Override
    public long getItemId(int position) {
        // TODO 自动生成的方法存根
        return position;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO 自动生成的方法存根
        return null;
    }
    public List<?> getMlist() {
        return mlist;
    }
    public void setMlist(List<?> mlist) {
        this.mlist = mlist;
    }
}


样例的代码中有个mlist变量,用来存在数据。对于所有的Adapter而言,它都会有自己的一个用来存放数据的变量,不行的话你可以去看看SimpleAdapter的源码。通常来讲,如果我们要动态的更新ListView或者GridView的内容,我只需要做两件事情:

1.更新对应的Adapter的数据,如上例中我们只要更新mlist变量;

2.通知Adapter数据已经更新了,使用Adapter.notifyDataSetChanged()可以通知数据的更新。

同样的,在ViewPager中的操作也几乎差不多,这里就不重复说明了。

原文出处:http://www.nuatar.com/Article.aspx?id=cfd1811415c54fc18a30b49302f7db36

原创粉丝点击