«

自定义ListView使用Volley获取数据

时间:2024-3-2 17:46     作者:韩俊     分类: Android


这是作为Volley框架使用的练习,如果对Volley框架的使用还不太熟悉,
建议先看前三篇文章:

Android Volley的使用(一)

Android Volley的使用(二)

Android Volley的使用(三)

本文代码github地址:UseVolley

要实现的效果如下:

Tips:以下大多数代码都是前三篇文章中详细介绍过的,在这里作为练习只提供一种思路,不再赘述

1,将Volley.jar添加进项目

获取Volley:

git clone 的方式

https://android.googlesource.com/platform/frameworks/volley
或者https://github.com/mcxiaoke/android-volley
你也可以直接下载 volley.jar

如果你是通过git clone方式,为了生成voller.jar你需要在你clone的volley目录下执行:

android update project -p

ant jar

将Volley添加进项目:

将volley.jar粘贴进libs文件夹下,然后右键volley.jar文件,选择Add as Library

2,创建ApplictionController类

public class ApplicationController extends Application {

    private static final String TAG= ApplicationController.class.getSimpleName();

    private RequestQueue requestQueue;
    private ImageLoader imageLoader;

    private static ApplicationController mInstance;
        @Override
        public void onCreate() {
        super.onCreate();
        mInstance=this;
    }

    public static synchronized ApplicationController getInstance(){
        return mInstance;
    }

    public RequestQueue getRequestQueue(){
        if(requestQueue==null)
            requestQueue= Volley.newRequestQueue(getApplicationContext());
        return requestQueue;
    }

    public ImageLoader getImageLoader(){
        getRequestQueue();
        if(imageLoader==null){
            imageLoader=new ImageLoader(requestQueue,new LruBitmapCache());
        }
        return imageLoader;
    }

    public <T> void addToRequestQueue(Request<T> req,String tag){
        req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);

        getRequestQueue().add(req);
    }

    public <T> void addToRequestQueue(Request<T> req){
        req.setTag(TAG);

        getRequestQueue().add(req);
    }

    public void cancelPendingRequest(Object tag){
        if(requestQueue!=null){
            requestQueue.cancelAll(tag);
        }
   }
 }

3,创建LruBitmapCache类

public class LruBitmapCache extends LruCache<String,Bitmap> implements ImageLoader.ImageCache {

    public static int getDefaultLruCacheSize(){
        final int maxMemory= (int) (Runtime.getRuntime().maxMemory()/1024);
        final int cacheSize=maxMemory/8;
        return cacheSize;

    }

    public LruBitmapCache(){
        this(getDefaultLruCacheSize());
    }
    public LruBitmapCache(int sizeInKiloBytes) {
        super(sizeInKiloBytes);
    }

    @Override
    protected int sizeOf(String key, Bitmap value) {
        return value.getRowBytes() * value.getHeight() / 1024;
    }

    @Override
    public Bitmap getBitmap(String url) {
        return get(url);
    }

    @Override
    public void putBitmap(String url, Bitmap bitmap) {
        put(url, bitmap);
    }
}

4,Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.coder.usevolley" >

   <uses-permission android:name="android.permission.INTERNET"/>
   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

   <application
        android:name=".ApplicationController"
        android:allowBackup="true"
        android:icon="@mipmap/icon_movie"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
            <activity
                android:icon="@mipmap/icon_movie"
                android:name=".MainActivity"
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />

                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
    </application>

</manifest>

以下这部分主要涉及如何自定义ListView视图,自定义Adapter

5,布局文件

activity_main.xml中添加一个ListView

 <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">
    <ListView
        android:id="@+id/movie_list"
        android:divider="#cccdde"
        android:dividerHeight="1dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </ListView>

</LinearLayout>

ListView中Item的视图:

在layout文件夹下创建movie_list_item.xml

这里的ImageView用的是Volley中的NetworkImageView,当然也可以直接用ImageView,二者稍有区别,详见Android Volley的使用(三)

布局我们可以采用RelativeLayout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:padding="8dp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <com.android.volley.toolbox.NetworkImageView
        android:id="@+id/movie_image"
        android:layout_alignParentLeft="true"
        android:layout_marginRight="8dp"
        android:layout_width="80dp"
        android:layout_height="80dp" />
    <TextView
        android:id="@+id/movie_name"
        android:layout_toRightOf="@+id/movie_image"
        android:layout_alignTop="@+id/movie_image"
        android:layout_marginTop="1dp"
        android:textSize="15sp"
        android:textStyle="bold"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/movie_rating"
        android:textColor="#f243"
        android:textSize="13sp"
        android:layout_marginTop="5dp"
        android:layout_below="@+id/movie_name"
        android:layout_toRightOf="@+id/movie_image"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/movie_year"
        android:textColor="#aaa"
        android:textSize="10sp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

6,定义数据模型:Movie

由于这里需要用数据请求,因此我创建了一个关于电影的Json数据movies.json,至于json数据的创建和服务端不是这次的内容,故不再说明,有兴趣的同学自己去了解。返回的数据格式如下:

所以我们需要定义一个movie类:

public class Movie {
        private String name;
        private String rating;
        private String image;
        private String year;

        public void setName(String name) {
            this.name = name;
        }

        public void setRating(String rating) {
            this.rating = rating;
        }

        public void setImage(String imageUrl) {
            this.image = imageUrl;
        }

        public void setYear(String year) {
            this.year = year;
        }

        public String getName() {
            return name;
        }

        public String getRating() {
            return rating;
        }

        public String getYear() {
            return year;
        }

        public String getImage() {
            return image;
        }

        public Movie(){}
        public Movie(String name,String rating,String imageUrl,String year){
            this.name=name;
            this.rating=rating;
            this.image=imageUrl;
            this.year=year;
        }
    }

7,自定义适配器类:MovieAdapter

我们需要将数据中的内容填充到ListView的Item中,即movie_list_item布局中,所以需要自定义适配器类:覆写其中的方法,getView()方法控制显示的视图

public class MovieAdapter extends BaseAdapter {

    private ArrayList<Movie> movies;
    private Activity activity;
    private LayoutInflater inflater;
    private ImageLoader imageLoader;

    private NetworkImageView movieImage;
    private TextView movieName,movieYear,movieRating;

    public MovieAdapter() {
        super();
    }
    public MovieAdapter(Activity activity,ArrayList<Movie> movies) {
        this.activity=activity;
        this.movies=movies;
    }

    @Override
    public int getCount() {
        return movies.size();
    }

    @Override
    public Object getItem(int i) {
        return movies.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        if (inflater == null)
            inflater = (LayoutInflater) activity
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if (view == null)
            view = inflater.inflate(R.layout.movie_list_item, null);

        if (imageLoader == null)
            imageLoader = ApplicationController.getInstance().getImageLoader();

        movieImage= (NetworkImageView) view.findViewById(R.id.movie_image);
        movieName= (TextView) view.findViewById(R.id.movie_name);
        movieRating= (TextView) view.findViewById(R.id.movie_rating);
        movieYear= (TextView) view.findViewById(R.id.movie_year);

                        movieImage.setImageUrl(movies.get(i).getImage(),imageLoader);
            movieName.setText((CharSequence) movies.get(i).getName());
            movieRating.setText("Rating:"+(CharSequence) movies.get(i).getRating());
            movieYear.setText((CharSequence) movies.get(i).getYear());

        return view;
    }
}

8,MainActivity

这部分才是我们需要真正实践Volley代码的部分

public class MainActivity extends ActionBarActivity {
    private static final String TAG=MainActivity.class.getSimpleName();

    private ArrayList<Movie> movies;
    private MovieAdapter adapter;
    private ListView movieList;

    private static final String url="http://www.jycoder.com/json/movies.json";

    private ProgressDialog pDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        movieList= (ListView) findViewById(R.id.movie_list);
        pDialog=new ProgressDialog(this);
        pDialog.setMessage("Loading...");
        pDialog.show();

        movies=new ArrayList<Movie>();

        fetchMovies();
        adapter=new MovieAdapter(MainActivity.this,movies);

        movieList.setAdapter(adapter);
    }

    private void fetchMovies() {

        JsonArrayRequest req=new JsonArrayRequest(url, new Response.Listener<JSONArray>() {

           @Override
           public void onResponse(JSONArray jsonArray) {

               new Handler().postDelayed(new Runnable() {
                   @Override
                   public void run() {
                      hidePDialog();
                   }
                },1000);
               for(int i=0;i<jsonArray.length();i++){
                   try {
                       JSONObject object=jsonArray.getJSONObject(i);
                       Movie movie=new Movie();
                       movie.setImage(object.getString("image"));
                        movie.setName(object.getString("name"));
                        movie.setRating(object.getString("rating"));
                        movie.setYear(object.getString("year"));

                       movies.add(movie);
                    } catch (JSONException e) {
                       e.printStackTrace();
                   }

               }
                //注意刷新数据
               adapter.notifyDataSetChanged();
           }
       }, new Response.ErrorListener() {
           @Override
           public void onErrorResponse(VolleyError volleyError) {
               Log.e(TAG,"error:"+volleyError.getMessage());
               hidePDialog();
           }
       });
       ApplicationController.getInstance().addToRequestQueue(req);
    }

        public void hidePDialog(){
            if(pDialog!=null)
                pDialog.dismiss();
            pDialog=null;
        }

        @Override
        protected void onDestroy() {
            super.onDestroy();
            hidePDialog();
        }

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.menu_main, menu);
            return true;
        }
    }

总结:

上面的很多代码都是我们在学习Volley框架中实现过的,所以只要正在掌握了Volley,以后使用的时候是很容易的,至于自定义ListView部分不太熟悉的可以参考下面这篇文章,有学Android小伙伴加微信共同进步哦~

参考资料:Android working with Volley Library

微博: @明桑Android黑历史
邮箱: <13141459344@163.com>

个人主页: 明桑战胜Android汪的黑历史

标签: android

热门推荐