这是作为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汪的黑历史