这一篇blog其实是没有什么新的知识点,就是接着上一篇的。然后会在FirstFragment中的tab01界面上使用一个ListView,然后这个listview会显示从网路上读取得到的数据。数据包括图片和文字,使用ImageLoader去下载并管理图片的一些处理,包括二级缓存(内存缓存和本地缓存)。
以前的代码没有修改,是在FirstFragment的tab01这个内容Fragment里面去处理。
主要的思路跟ListView使用ImageLoader去下载图片显示一样。首先需要配置Application,里面对ImageLoader做初始化配置。然后在tab01,也就是显示内容的Fragment中使用LIstVIew控件,自定义适配器,然后使用Handler机制绑定适配器。使用Fragment'可以把它当做Activity那样子去使用,当时需要注意的就是Fragment的生命周期以及他们执行顺序,执行效果。其中,假如是使用ViewPager+Fragment的时候特别需要注意,我们的ViewPager'会缓存相邻界面,比如当前界面是1,滑动到2的时候2界面会缓存1界面(此时还没有滑动到3界面),当滑动到3界面的时候,他只会缓存2界面,这时候关于1界面就会被销毁。假如需要缓存多个界面,不用去考虑性能优化可以使用mViewPager.setOffscreenPageLimit(2); 这个方法,他可以缓存两个Fragment页面。上代码首先是tab01的界面:
废话不多说,上代码:
首先是Tab01的布局,就是一个ListView
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" > <ListView android:id="@+id/tab_01_listView" android:layout_width="match_parent" android:layout_height="match_parent" > </ListView></LinearLayout>
到LIstView所绑定数据条目的显示界面的代码:包含一个ImageView和两个TextView
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ImageView android:src="@drawable/ic_launcher" android:id="@+id/id_ListView_imageView" android:layout_width="72dp" android:layout_height="72dp" android:layout_margin="5dp" android:adjustViewBounds="true" android:contentDescription="@string/contentDescriptionImage" android:scaleType="centerCrop" /> <TextView android:textStyle="bold" android:id="@+id/news_list_tit" android:layout_width="wrap_content" android:layout_height="25dp" android:layout_alignParentTop="true" android:layout_marginLeft="16dp" android:layout_toRightOf="@id/id_ListView_imageView" android:text="DFGDFGDFGD" android:textSize="18sp" android:textColor="#000000"/> <TextView android:layout_marginTop="3dp" android:textSize="15sp" android:textColor="#000000" android:id="@+id/news_list_cont" android:layout_width="wrap_content" android:layout_height="25dp" android:layout_alignLeft="@+id/news_list_tit" android:layout_below="@id/news_list_tit" android:gravity="bottom" android:text="00000000000" /> <TextView android:textSize="12sp" android:textStyle="italic" android:textColor="#000000" android:id="@+id/news_list_gentie" android:layout_width="100dp" android:layout_height="25dp" android:layout_alignParentRight="true" android:layout_below="@+id/news_list_cont" android:gravity="right" android:text="520跟帖" /></RelativeLayout>
import java.util.ArrayList;import java.util.List;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.support.v4.app.Fragment;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ListView;import android.widget.Toast;import com.example.mytoolbar_04.R;import com.example.mytoolbar_04.fragment.adapter.MyTab01BaseAdapter;import com.example.mytoolbar_04.fragment.domain.NewsInfo;import com.example.mytoolbar_04.fragment.service.TabNewsService;import com.nostra13.universalimageloader.core.DisplayImageOptions;import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer;public class Tab01 extends Fragment{ public static final int OK = 1; public static final int ERROR = -1; private ListView mTab01ListView; private View mTab01LayoutView; private List<NewsInfo> datas; private DisplayImageOptions options; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mTab01LayoutView = inflater.inflate(R.layout.tab01, null); mTab01ListView = (ListView) mTab01LayoutView.findViewById(R.id.tab_01_listView); datas = new ArrayList<NewsInfo>(); new MyLoaderNewInfo(datas, mHandler).start(); options = new DisplayImageOptions.Builder().showStubImage(R.drawable.ic_launcher) .showImageForEmptyUri(R.drawable.ic_empty).showImageOnFail(R.drawable.ic_error) .displayer(new RoundedBitmapDisplayer(20)).build(); return mTab01LayoutView; } //绑定适配器 private Handler mHandler = new Handler() { @SuppressWarnings("unchecked") public void handleMessage(Message msg) { if (msg.what == OK) { MyTab01BaseAdapter adapter = new MyTab01BaseAdapter(getActivity(), options, (List<NewsInfo>) msg.obj); mTab01ListView.setAdapter(adapter); } if (msg.what == ERROR) { Toast.makeText(getActivity(), "获取失败", Toast.LENGTH_SHORT).show(); } }; };}class MyLoaderNewInfo extends Thread{ private List<NewsInfo> datas; private Handler mHandler; public MyLoaderNewInfo(List<NewsInfo> datas, Handler mHandler) { this.datas = datas; this.mHandler = mHandler; } /* (non-Javadoc) * @see java.lang.Thread#run() * 下载xml基础数据 */ @Override public void run() { try { datas.addAll(TabNewsService.getDatas()); Message msg = Message.obtain(); msg.what = Tab01.OK; msg.obj = datas; mHandler.sendMessage(msg); } catch (Exception e) { e.printStackTrace(); mHandler.sendEmptyMessage(Tab01.ERROR); } }}到获取XML基础数据的Service类了,也没撒好说的,;利用Pull破解器解析xml数据,返回一个List集合
import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;import java.util.ArrayList;import java.util.List;import org.xmlpull.v1.XmlPullParser;import org.xmlpull.v1.XmlPullParserException;import android.util.Xml;import com.example.mytoolbar_04.fragment.domain.NewsInfo;/** * @author Administrator liweijie * 初次获取网络基本数据 */public class TabNewsService{ // 192.168.1.137mylist1.xml /** * 请求xml数据 * @return * @throws Exception * @throws XmlPullParserException */ public static List<NewsInfo> getDatas() throws XmlPullParserException, Exception { String path = "http://172.21.123.11:8080/web/News.xml"; HttpURLConnection conn = (HttpURLConnection) new URL(path).openConnection(); conn.setReadTimeout(5000); conn.setConnectTimeout(5000); conn.setRequestMethod("GET"); if (200 == conn.getResponseCode()) { InputStream stream = conn.getInputStream(); return parXML(stream); } return null; } /** * 解析xml数据 * @param stream * @return * @throws XmlPullParserException * @throws Exception */ private static List<NewsInfo> parXML(InputStream stream) throws XmlPullParserException, Exception { List<NewsInfo> datas = new ArrayList<NewsInfo>(); NewsInfo news = null; XmlPullParser parser = Xml.newPullParser(); parser.setInput(stream, "UTF-8"); int event = parser.getEventType(); while (event != XmlPullParser.END_DOCUMENT) { switch (event) { case XmlPullParser.START_TAG: if("picture".equals(parser.getName())) { news = new NewsInfo(); news.setTitle(parser.getAttributeValue(0)); break; } if("path".equals(parser.getName())) { news.setPath(parser.nextText()); break; } if("content".equals(parser.getName())) { news.setContent(parser.nextText()); break; } if("fllow".equals(parser.getName())) { news.setPeopleIN(parser.nextText()); break; } break; case XmlPullParser.END_TAG: if ("picture".equals(parser.getName())) { datas.add(news); news = null; break; } break; } event = parser.next(); } System.out.println(datas.size()); return datas; }}domian类
public class NewsInfo{ private String path; private String title; private String content; private String peopleIN; public NewsInfo(){}; public NewsInfo(String path, String title, String content, String peopleIN) { super(); this.path = path; this.title = title; this.content = content; this.peopleIN = peopleIN; } public String getPath() { return path; } public void setPath(String path) { this.path = path; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getPeopleIN() { return peopleIN; } public void setPeopleIN(String peopleIN) { this.peopleIN = peopleIN; }}
import java.util.ArrayList;import java.util.Collections;import java.util.LinkedList;import java.util.List;import android.content.Context;import android.graphics.Bitmap;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.TextView;import com.example.mytoolbar_04.MainActivity;import com.example.mytoolbar_04.R;import com.example.mytoolbar_04.fragment.domain.NewsInfo;import com.nostra13.universalimageloader.core.DisplayImageOptions;import com.nostra13.universalimageloader.core.ImageLoader;import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;public class MyTab01BaseAdapter extends BaseAdapter{ private LayoutInflater inflater; private List<NewsInfo> datas = new ArrayList<NewsInfo>(); private DisplayImageOptions options; private ImageLoader imageLoader = MainActivity.getImageLoader(); public MyTab01BaseAdapter(Context activity, DisplayImageOptions options, List<NewsInfo> datas) { this.datas.addAll(datas); inflater = LayoutInflater.from(activity); this.options = options; System.out.println("ok222"); } public int getCount() { return datas.size(); } public Object getItem(int position) { return datas.get(position); } @Override public long getItemId(int position) { return position; } private NewsInfo news; @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (convertView == null) { holder = new ViewHolder(); convertView = inflater.inflate(R.layout.newlistview_layout_item, null); holder.imageView = (ImageView) convertView.findViewById(R.id.id_ListView_imageView); holder.mTitle = (TextView) convertView.findViewById(R.id.news_list_tit); holder.mContent = (TextView) convertView.findViewById(R.id.news_list_cont); holder.mFllow = (TextView) convertView.findViewById(R.id.news_list_gentie); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } System.out.println("66666"); news = datas.get(position); holder.mTitle.setText(news.getTitle()); holder.mContent.setText(news.getContent()); holder.mFllow.setText(news.getPeopleIN()); imageLoader.displayImage(news.getPath(), holder.imageView,options,new FirstDisplatListener()); return convertView; } class ViewHolder { ImageView imageView; TextView mTitle; TextView mContent; TextView mFllow; } private static class FirstDisplatListener extends SimpleImageLoadingListener { static final List<String> diaplayImages = Collections .synchronizedList(new LinkedList<String>());// 线程安全 @Override public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { if (loadedImage == null) { ImageView imageView = (ImageView) view; boolean firstDisplay = !diaplayImages.contains(imageUri); if (firstDisplay)// 不存在的时候,这时候是属于第一次显示,使用一个渐变的动画,然后把该uri对应的imageview存放到list中 { FadeInBitmapDisplayer.animate(imageView, 500); diaplayImages.add(imageUri); } } } }}还有Application类,需要在Application界面使用name属性去使用它
import java.io.File;import android.app.Application;import android.content.Context;import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache;import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;import com.nostra13.universalimageloader.core.ImageLoader;import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;import com.nostra13.universalimageloader.core.assist.QueueProcessingType;import com.nostra13.universalimageloader.utils.StorageUtils;public class MyApplication extends Application{ @Override public void onCreate() { super.onCreate(); initImageLoader(getApplicationContext()); } private static void initImageLoader(Context context) { File cache = StorageUtils.getOwnCacheDirectory(context, "operaPic/cache"); ImageLoaderConfiguration configuration = new ImageLoaderConfiguration.Builder(context) .threadPriority(Thread.NORM_PRIORITY - 2) .threadPoolSize(4) .discCache(new UnlimitedDiscCache(cache)) .denyCacheImageMultipleSizesInMemory() .discCacheFileNameGenerator(new Md5FileNameGenerator()) .tasksProcessingOrder(QueueProcessingType.LIFO) .writeDebugLogs() .build(); ImageLoader.getInstance().init(configuration); }}
我这篇demo是使用ViewPager+Fragment的,没有使用mViewPager.setOffscreenPageLimit(2)这个API,所以只会默认缓存一个页面
下面是效果图:可以注意到当移动到2界面返回1界面的时候没有1界面变化,但是当从3界面移动到1界面的时候他会从新去调用onCreateView方法去重新创建Fragment的view。当LeftMenuFragment的切换过程发现其他的Fragment之前切换是不会影响他的布局的,因为我们显示FirstFragment和SecondFragment以及ThirdFragment的时候是先hide在shou,不会对Fragment的显示造成什么样的影响。