您的位置:首页 > 其它

谷歌应用市场2

2015-08-17 14:45 495 查看

1.抽取到BaseFragment

1.把共性代码提取出来---各方法的注释见第一天代码
(1)每个界面都有4种界面,5种状态
public static final int STATE_UNKOWN = 0;
public static final int STATE_LOADING = 1;
public static final int STATE_ERROR = 2;
public static final int STATE_EMPTY = 3;
public static final int STATE_SUCCESS = 4;
public static int state = STATE_UNKOWN;

private View loadingView;// 加载中的界面
private View errorView;// 错误界面
private View emptyView;// 空界面
private View successView;// 加载成功的界面
private FrameLayout frameLayout;


(2)每个界面都有一个Fraglayout帧布局
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if(frameLayout==null){
frameLayout = new FrameLayout(getActivity());
init(); // 在FrameLayout中 添加4种不同的界面
}else{
ViewUtils.removeParent(frameLayout);// 移除frameLayout之前的爹
}

// showPage();// 根据不同的状态显示不同的界面
show();// 根据服务器的数据 切换状态

return frameLayout;

}


(3)init方法
// 添加4种不同界面
private void init() {
loadingView = createLoadingView(); // 创建了加载中的界面
if (loadingView != null) {
frameLayout.addView(loadingView, new FrameLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
}
errorView = createErrorView(); // 加载错误界面
if (errorView != null) {
frameLayout.addView(errorView, new FrameLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
}
emptyView = createEmptyView(); // 加载空的界面
if (emptyView != null) {
frameLayout.addView(emptyView, new FrameLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
}

showPage();// 根据不同的状态显示不同的界面
}


(4)showPager方法
// 根据不同的状态显示不同的界面
private void showPage() {
if (loadingView != null) {
loadingView.setVisibility(state == STATE_UNKOWN
|| state == STATE_LOADING ? View.VISIBLE : View.INVISIBLE);
}
if (errorView != null) {
errorView.setVisibility(state == STATE_ERROR ? View.VISIBLE
: View.INVISIBLE);
}
if (emptyView != null) {
emptyView.setVisibility(state == STATE_EMPTY ? View.VISIBLE
: View.INVISIBLE);
}
if (state == STATE_SUCCESS) {
successView = createSuccessView();
if (successView != null) {
frameLayout.addView(successView, new FrameLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
successView.setVisibility(View.VISIBLE);
}
}
}


(5)创建界面的方法相同
// 创建界面
private View createEmptyView() {
View view = View.inflate(getActivity(), R.layout.loadpage_empty, null);
return view;
}

private View createErrorView() {
View view = View.inflate(getActivity(), R.layout.loadpage_error, null);
Button page_bt = (Button) view.findViewById(R.id.page_bt);
page_bt.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
show();
}
});
return view;
}

private View createLoadingView() {
View view = View
.inflate(getActivity(), R.layout.loadpage_loading, null);
return view;
}


(6)show方法
public enum LoadResult {
error(2), empty(3), success(4);

int value;

LoadResult(int value) {
this.value = value;
}

public int getValue() {
return value;
}

}

// 根据服务器的数据切换状态
private void show() {
if (state == STATE_ERROR || state == STATE_EMPTY) {
state = STATE_LOADING;
}
// 请求服务器 获取服务器上数据 进行判断
// 请求服务器 返回一个结果
// 请求服务器 在子线程中执行,但改变界面需要在主线程中执行,所以使用runOnUiThread
new Thread() {
public void run() {
SystemClock.sleep(2000);
final LoadResult result = load();
if (getActivity() != null) {
getActivity().runOnUiThread(new Runnable() {

@Override
public void run() {
if (result != null) {
state = result.getValue();
showPage(); // 状态改变了,重新判断当前应该显示哪个界面
}
}
});
}
};
}.start();
showPage();

}


(7)成功界面变为抽象,由子类实现
public  abstract View createSuccessView();


(8)请求服务器的方法也变为抽象,由子类实现
public abstract LoadResult load();


2.让每一个Pager滑动时都重新加载数据
(1)在MainActivity中为ViewPager设置监听事件
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener(){

@Override
public void onPageSelected(int position) {
super.onPageSelected(position);
BaseFragment createFragment = FragmentFactory.createFragment(position);
createFragment.show();//  当切换界面的时候 重新请求服务器
}

});


show方法只调用一次,只在ViewPager滑动时调用
(2)第一次打开应用时没有调用show方法,为首页单独设置一个show方法
// 当Fragment挂载的activity创建的时候调用
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
show();
}


3.不能把状态改为静态
public   int state = STATE_UNKOWN;


4.总结:BaseFragment的代码
public abstract class BaseFragment extends Fragment {
public static final int STATE_UNKOWN = 0;
public static final int STATE_LOADING = 1;
public static final int STATE_ERROR = 2;
public static final int STATE_EMPTY = 3;
public static final int STATE_SUCCESS = 4;
public int state = STATE_UNKOWN;

private View loadingView;// 加载中的界面
private View errorView;// 错误界面
private View emptyView;// 空界面
private View successView;// 加载成功的界面
private FrameLayout frameLayout;

public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if(frameLayout==null){
frameLayout = new FrameLayout(getActivity());
init(); // 在FrameLayout中 添加4种不同的界面
}else{
ViewUtils.removeParent(frameLayout);// 移除frameLayout之前的爹
}

// showPage();// 根据不同的状态显示不同的界面
// show();// 根据服务器的数据 切换状态

return frameLayout;

}

// 添加4种不同界面 private void init() { loadingView = createLoadingView(); // 创建了加载中的界面 if (loadingView != null) { frameLayout.addView(loadingView, new FrameLayout.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); } errorView = createErrorView(); // 加载错误界面 if (errorView != null) { frameLayout.addView(errorView, new FrameLayout.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); } emptyView = createEmptyView(); // 加载空的界面 if (emptyView != null) { frameLayout.addView(emptyView, new FrameLayout.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); } showPage();// 根据不同的状态显示不同的界面 }

// 根据不同的状态显示不同的界面
private void showPage() {
if (loadingView != null) {
loadingView.setVisibility(state == STATE_UNKOWN
|| state == STATE_LOADING ? View.VISIBLE : View.INVISIBLE);
}
if (errorView != null) {
errorView.setVisibility(state == STATE_ERROR ? View.VISIBLE
: View.INVISIBLE);
}
if (emptyView != null) {
emptyView.setVisibility(state == STATE_EMPTY ? View.VISIBLE
: View.INVISIBLE);
}
if (state == STATE_SUCCESS) {
successView = createSuccessView();
if (successView != null) {
frameLayout.addView(successView, new FrameLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
successView.setVisibility(View.VISIBLE);
}
}else{
if (successView != null) {
successView.setVisibility(View.INVISIBLE);
}
}
}

public abstract View createSuccessView();

public enum LoadResult {
error(2), empty(3), success(4);

int value;

LoadResult(int value) {
this.value = value;
}

public int getValue() {
return value;
}

}

// 根据服务器的数据切换状态
public void show() {
if (state == STATE_ERROR || state == STATE_EMPTY) {
state = STATE_LOADING;
}
// 请求服务器 获取服务器上数据 进行判断
// 请求服务器 返回一个结果
// 请求服务器 在子线程中执行,但改变界面需要在主线程中执行,所以使用runOnUiThread
new Thread() {
public void run() {
SystemClock.sleep(2000);
final LoadResult result = load();
if (getActivity() != null) {
getActivity().runOnUiThread(new Runnable() {

@Override
public void run() {
if (result != null) {
state = result.getValue();
showPage(); // 状态改变了,重新判断当前应该显示哪个界面
}
}
});
}
};
}.start();
showPage();

}

public abstract LoadResult load();
// 创建界面 private View createEmptyView() { View view = View.inflate(getActivity(), R.layout.loadpage_empty, null); return view; } private View createErrorView() { View view = View.inflate(getActivity(), R.layout.loadpage_error, null); Button page_bt = (Button) view.findViewById(R.id.page_bt); page_bt.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { show(); } }); return view; } private View createLoadingView() { View view = View .inflate(getActivity(), R.layout.loadpage_loading, null); return view; }
}


2.代码摘取到loadingPage

1.BaseFragment来回操作的都是FrameLayout,所以把它抽离出来

1.自定义一个控件,继承FrameLayout,防止BaseFragment中代码过于臃肿
/***
* 创建了自定义帧布局 把baseFragment 一部分代码 抽取到这个类中
*
* @author itcast
*
*/
public abstract class LoadingPage extends FrameLayout {

public static final int STATE_UNKOWN = 0;
public static final int STATE_LOADING = 1;
public static final int STATE_ERROR = 2;
public static final int STATE_EMPTY = 3;
public static final int STATE_SUCCESS = 4;
public int state = STATE_UNKOWN;

private View loadingView;// 加载中的界面
private View errorView;// 错误界面
private View emptyView;// 空界面
private View successView;// 加载成功的界面

public LoadingPage(Context context) {
super(context);
init();
}

public LoadingPage(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}

public LoadingPage(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}

private void init() {
loadingView = createLoadingView(); // 创建了加载中的界面
if (loadingView != null) {
this.addView(loadingView, new FrameLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
}
errorView = createErrorView(); // 加载错误界面
if (errorView != null) {
this.addView(errorView, new FrameLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
}
emptyView = createEmptyView(); // 加载空的界面
if (emptyView != null) {
this.addView(emptyView, new FrameLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
}
showPage();// 根据不同的状态显示不同的界面
}

// 根据不同的状态显示不同的界面
private void showPage() {
if (loadingView != null) {
loadingView.setVisibility(state == STATE_UNKOWN
|| state == STATE_LOADING ? View.VISIBLE : View.INVISIBLE);
}
if (errorView != null) {
errorView.setVisibility(state == STATE_ERROR ? View.VISIBLE
: View.INVISIBLE);
}
if (emptyView != null) {
emptyView.setVisibility(state == STATE_EMPTY ? View.VISIBLE
: View.INVISIBLE);
}
if (state == STATE_SUCCESS) {
if (successView == null) {
successView = createSuccessView();
this.addView(successView, new FrameLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
}
successView.setVisibility(View.VISIBLE);
} else {
if (successView != null) {
successView.setVisibility(View.INVISIBLE);
}
}
}

/* 创建了空的界面 */
private View createEmptyView() {
View view = View.inflate(UiUtils.getContext(), R.layout.loadpage_empty,
null);
return view;
}

/* 创建了错误界面 */
private View createErrorView() {
View view = View.inflate(UiUtils.getContext(), R.layout.loadpage_error,
null);
Button page_bt = (Button) view.findViewById(R.id.page_bt);
page_bt.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
show();
}
});
return view;
}

/* 创建加载中的界面 */
private View createLoadingView() {
View view = View.inflate(UiUtils.getContext(),
R.layout.loadpage_loading, null);
return view;
}

public enum LoadResult {
error(2), empty(3), success(4);

int value;

LoadResult(int value) {
this.value = value;
}

public int getValue() {
return value;
}

}

// 根据服务器的数据 切换状态
public void show() {
if (state == STATE_ERROR || state == STATE_EMPTY) {
state = STATE_LOADING;
}
// 请求服务器 获取服务器上数据 进行判断
// 请求服务器 返回一个结果
ThreadManager.getInstance().createLongPool().execute(new Runnable() {

@Override
public void run() {
SystemClock.sleep(2000);
final LoadResult result = load();
UiUtils.runOnUiThread(new Runnable() {

@Override
public void run() {
if (result != null) {
state = result.getValue();
showPage(); // 状态改变了,重新判断当前应该显示哪个界面
}
}
});
}
});

showPage();

}

/***
* 创建成功的界面
*
* @return
*/
public abstract View createSuccessView();

/**
* 请求服务器
*
* @return
*/
protected abstract LoadResult load();
}


2.BaseFragment中代码
public abstract class BaseFragment extends Fragment {

private LoadingPage loadingPage;
protected BitmapUtils bitmapUtils;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
bitmapUtils = BitmapHelper.getBitmapUtils();

if (loadingPage == null) {  // 之前的frameLayout 已经记录了一个爹了  爹是之前的ViewPager
loadingPage = new LoadingPage(getActivity()){

@Override
public View createSuccessView() {
return BaseFragment.this.createSuccessView();
}

@Override
protected LoadResult load() {
return BaseFragment.this.load();
}
};
}else{
ViewUtils.removeParent(loadingPage);// 移除frameLayout之前的爹
}

return loadingPage;  //  拿到当前viewPager 添加这个framelayout
}
/***
*  创建成功的界面
* @return
*/
public  abstract View createSuccessView();
/**
* 请求服务器
* @return
*/
protected abstract LoadResult load();

public void show(){
if(loadingPage!=null){
loadingPage.show();
}
}

/**校验数据 */
public LoadResult checkData(List datas) {
if(datas==null){
return LoadResult.error;//  请求服务器失败
}else{
if(datas.size()==0){
return LoadResult.empty;
}else{
return LoadResult.success;
}
}

}

}


3.线程池原理和具体实现

1.用线程池管理线程

(1)一般都是直接回收线程,线程池是把它保存下来,提高效率

2.线程池原理 Demo

public class ThreadPool {
int maxCount = 3;
AtomicInteger count =new AtomicInteger(0);// 当前开的线程数  count=0
LinkedList<Runnable> runnables = new LinkedList<Runnable>();

public void execute(Runnable runnable) {
runnables.add(runnable);
if(count.incrementAndGet()<=3){
createThread();
}
}
private void createThread() {
new Thread() {
@Override
public void run() {
super.run();
while (true) {
// 取出来一个异步任务
if (runnables.size() > 0) {
Runnable remove = runnables.remove(0);
if (remove != null) {
remove.run();
}
}else{
//  等待状态   wake();
}
}
}
}.start();
}
}


3.根据不同业务创建不同线程池,线程池管理者

(1)线程池管理者

/**
* 管理线程池
*
* @author itcast
*
*/
public class ThreadManager {
private ThreadManager() {

}

private static ThreadManager instance = new ThreadManager();
private ThreadPoolProxy longPool;
private ThreadPoolProxy shortPool;

public static ThreadManager getInstance() {
return instance;
}
//******************一般创建多个线程池,联网和操作本地文件一般分开,根据不同业务开不同线程池
// 联网比较耗时
// cpu的核数*2+1     开多少个线程最合适
public synchronized ThreadPoolProxy createLongPool() {     //自己定义的方法创建线程池,Long适合长时间的
if (longPool == null) {
longPool = new ThreadPoolProxy(5, 5, 5000L);
}
return longPool;
}
// 操作本地文件
public synchronized ThreadPoolProxy createShortPool() {   //适合短时间的
if(shortPool==null){
shortPool = new ThreadPoolProxy(3, 3, 5000L);
}
return shortPool;
}
//******************************************************
public class ThreadPoolProxy {
private ThreadPoolExecutor pool;
private int corePoolSize;
private int maximumPoolSize;
private long time;

public ThreadPoolProxy(int corePoolSize, int maximumPoolSize, long time) {
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.time = time;

}
/**
* 执行任务
* @param runnable
*/
public void execute(Runnable runnable) {
if (pool == null) {
// 创建线程池
/*
* 1. 线程池里面管理多少个线程2. 如果排队满了, 额外的开的线程数3. 如果线程池没有要执行的任务 存活多久4.
* 时间的单位 5 如果 线程池里管理的线程都已经用了,剩下的任务 临时存到LinkedBlockingQueue对象中 排队
*/
pool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize,
time, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(10));
}
pool.execute(runnable); // 调用线程池 执行异步任务
}
/**
* 取消任务
* @param runnable
*/
public void cancel(Runnable runnable) {
if (pool != null && !pool.isShutdown() && !pool.isTerminated()) {
pool.remove(runnable); // 取消异步任务
}
}
}
}


(2)使用
// 请求服务器 获取服务器上数据 进行判断
// 请求服务器 返回一个结果
ThreadManager.getInstance().createLongPool().execute(new Runnable() {

@Override
public void run() {
SystemClock.sleep(2000);
final LoadResult result = load();
UiUtils.runOnUiThread(new Runnable() {

@Override
public void run() {
if (result != null) {
state = result.getValue();
showPage(); // 状态改变了,重新判断当前应该显示哪个界面
}
}
});
}
});


4.以后使用线程时习惯使用线程池,因为开多个线程池比较消耗内存

4.请求服务器的框架

1.写一个类专门操作联网

2.搭建框架

public class HomeProtocol {
public void load(int index) {
String json = loadLocal(index); //获取本地的
if (json == null) {
json = loadServer();        //联网获取
if (json != null) {
saveLocal(json, index);
}
}
if (json != null) {
paserJson(json);            //解析json
}
}
}


3.再每一个去实现

5.联网

1.权限

2.解决工程部分类乱码方法,编码不一致

1.从XUtils抽取3个类,用于联网,可直接用
(1) HttpClientFactory.java

public class HttpClientFactory {
/** http请求最大并发连接数 */
private static final int MAX_CONNECTIONS = 10;
/** 超时时间 */
private static final int TIMEOUT = 10 * 1000;
/** 缓存大小 */
private static final int SOCKET_BUFFER_SIZE = 8 * 1024; // 8KB
/** 错误尝试次数,错误异常表请在RetryHandler添加 */
private static final int MAX_RETRIES = 5;
private static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding";
private static final String ENCODING_GZIP = "gzip";

public static DefaultHttpClient create(boolean isHttps) {
HttpParams params = createHttpParams();
DefaultHttpClient httpClient = null;
if (isHttps) {
// 支持http与https
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
// ThreadSafeClientConnManager线程安全管理类
ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);
httpClient = new DefaultHttpClient(cm, params);
} else {
httpClient = new DefaultHttpClient(params);
}
return httpClient;
}

private static HttpParams createHttpParams() {
final HttpParams params = new BasicHttpParams();
// 设置是否启用旧连接检查,默认是开启的。关闭这个旧连接检查可以提高一点点性能,但是增加了I/O错误的风险(当服务端关闭连接时)。
// 开启这个选项则在每次使用老的连接之前都会检查连接是否可用,这个耗时大概在15-30ms之间
HttpConnectionParams.setStaleCheckingEnabled(params, false);
HttpConnectionParams.setConnectionTimeout(params, TIMEOUT);// 设置链接超时时间
HttpConnectionParams.setSoTimeout(params, TIMEOUT);// 设置socket超时时间
HttpConnectionParams.setSocketBufferSize(params, SOCKET_BUFFER_SIZE);// 设置缓存大小
HttpConnectionParams.setTcpNoDelay(params, true);// 是否不使用延迟发送(true为不延迟)
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); // 设置协议版本
HttpProtocolParams.setUseExpectContinue(params, true);// 设置异常处理机制
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);// 设置编码
HttpClientParams.setRedirecting(params, false);// 设置是否采用重定向

ConnManagerParams.setTimeout(params, TIMEOUT);// 设置超时
ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRouteBean(MAX_CONNECTIONS));// 多线程最大连接数
ConnManagerParams.setMaxTotalConnections(params, 10); // 多线程总连接数
return params;
}

private static void createHttpClient(DefaultHttpClient httpClient) {
// 添加request的拦截器,添加必要的头信息
httpClient.addRequestInterceptor(new HttpRequestInterceptor() {
public void process(HttpRequest request, HttpContext context) {
if (!request.containsHeader(HEADER_ACCEPT_ENCODING)) {
request.addHeader(HEADER_ACCEPT_ENCODING, ENCODING_GZIP);
}
}
});

// 添加response拦截器,预先对response进行一些处理
httpClient.addResponseInterceptor(new HttpResponseInterceptor() {
public void process(HttpResponse response, HttpContext context) {
final HttpEntity entity = response.getEntity();
if (entity == null) {
return;
}
final Header encoding = entity.getContentEncoding();
if (encoding != null) {
for (HeaderElement element : encoding.getElements()) {
// 如果是以GZIP压缩的数据,利用内部的填充器包装一层Gzip的流
if (element.getName().equalsIgnoreCase(ENCODING_GZIP)) {
response.setEntity(new InflatingEntity(response.getEntity()));
break;
}
}
}
}
});
// 设置重试次数
httpClient.setHttpRequestRetryHandler(new HttpRetry(MAX_RETRIES));
}

/** 当服务器返回的数据是以Gzip压缩的过后的数据,填充Response返回的实体数据 (Description),则返回GZIP解压流 */
private static class InflatingEntity extends HttpEntityWrapper {
public InflatingEntity(HttpEntity wrapped) {
super(wrapped);
}

@Override
public InputStream getContent() throws IOException {
return new GZIPInputStream(wrappedEntity.getContent());
}

// 因为数据是压缩数据,所以实际长度无法估计,可以返回-1
@Override
public long getContentLength() {
return -1;
}
}

/** 自定义的安全套接字协议的实现,目前采用默认的,未使用到 */
private static class SSLSocketFactoryEx extends SSLSocketFactory {
// 此类的实例表示安全套接字协议的实现,它充当用于安全套接字工厂或 SSLEngine 的工厂。用可选的一组密钥和信任管理器及安全随机字节源初始化此类。
SSLContext sslContext = SSLContext.getInstance("TLS");

public SSLSocketFactoryEx(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
super(truststore);
// TrustManager负责管理做出信任决定时使用的的信任材料,也负责决定是否接受同位体提供的凭据。
// X509TrustManager此接口的实例管理使用哪一个 X509 证书来验证远端的安全套接字。决定是根据信任的证书授权、证书撤消列表、在线状态检查或其他方式做出的。
TrustManager tm = new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;// 返回受验证同位体信任的认证中心的数组。
}

@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {
// 给出同位体提供的部分或完整的证书链,构建到可信任的根的证书路径,并且返回是否可以确认和信任将其用于基于验证类型的客户端 SSL 验证。
}

@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {
// 给出同位体提供的部分或完整的证书链,构建到可信任的根的证书路径,并且返回是否可以确认和信任将其用于基于验证类型的服务器 SSL 验证。
}
};
sslContext.init(null, new TrustManager[]{tm}, null);
}

@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
}

@Override
public Socket createSocket() throws IOException {
return sslContext.getSocketFactory().createSocket();
}
}
}


(2)HttpHelper.java
<span style="font-size:14px;">public class HttpHelper {

public static final String URL = "http://127.0.0.1:8090/";

/** get请求,获取返回字符串内容 */
public static HttpResult get(String url) {
HttpGet httpGet = new HttpGet(url);
return execute(url, httpGet);
}

/** post请求,获取返回字符串内容 */
public static HttpResult post(String url, byte[] bytes) {
HttpPost httpPost = new HttpPost(url);
ByteArrayEntity byteArrayEntity = new ByteArrayEntity(bytes);
httpPost.setEntity(byteArrayEntity);
return execute(url, httpPost);
}

/** 下载 */
public static HttpResult download(String url) {
HttpGet httpGet = new HttpGet(url);
return execute(url, httpGet);
}

/** 执行网络访问 */
private static HttpResult execute(String url, HttpRequestBase requestBase) {
boolean isHttps = url.startsWith("https://");//判断是否需要采用https
AbstractHttpClient httpClient = HttpClientFactory.create(isHttps);
HttpContext httpContext = new SyncBasicHttpContext(new BasicHttpContext());
HttpRequestRetryHandler retryHandler = httpClient.getHttpRequestRetryHandler();//获取重试机制
int retryCount = 0;
boolean retry = true;
while (retry) {
try {
HttpResponse response = httpClient.execute(requestBase, httpContext);//访问网络
if (response != null) {
return new HttpResult(response, httpClient, requestBase);
}
} catch (Exception e) {
IOException ioException = new IOException(e.getMessage());
retry = retryHandler.retryRequest(ioException, ++retryCount, httpContext);//把错误异常交给重试机制,以判断是否需要采取从事
LogUtils.e(e);
}
}
return null;
}

/** http的返回结果的封装,可以直接从中获取返回的字符串或者流 */
public static class HttpResult {
private HttpResponse mResponse;
private InputStream mIn;
private String mStr;
private HttpClient mHttpClient;
private HttpRequestBase mRequestBase;

public HttpResult(HttpResponse response, HttpClient httpClient, HttpRequestBase requestBase) {
mResponse = response;
mHttpClient = httpClient;
mRequestBase = requestBase;
}

public int getCode() {
StatusLine status = mResponse.getStatusLine();
return status.getStatusCode();
}

/** 从结果中获取字符串,一旦获取,会自动关流,并且把字符串保存,方便下次获取 */
public String getString() {
if (!TextUtils.isEmpty(mStr)) {
return mStr;
}
InputStream inputStream = getInputStream();
ByteArrayOutputStream out = null;
if (inputStream != null) {
try {
out = new ByteArrayOutputStream();
byte[] buffer = new byte[1024 * 4];
int len = -1;
while ((len = inputStream.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
byte[] data = out.toByteArray();
mStr = new String(data, "utf-8");
} catch (Exception e) {
LogUtils.e(e);
} finally {
IOUtils.closeQuietly(out);
close();
}
}
return mStr;
}

/** 获取流,需要使用完毕后调用close方法关闭网络连接 */
public InputStream getInputStream() {
if (mIn == null && getCode() < 300) {
HttpEntity entity = mResponse.getEntity();
try {
mIn = entity.getContent();
} catch (Exception e) {
LogUtils.e(e);
}
}
return mIn;
}

/** 关闭网络连接 */
public void close() {
if (mRequestBase != null) {
mRequestBase.abort();
}
IOUtils.closeQuietly(mIn);
if (mHttpClient != null) {
mHttpClient.getConnectionManager().closeExpiredConnections();
}
}
}
}
</span>


(3)HttpRetry.java
public class HttpRetry implements HttpRequestRetryHandler {
// 重试休息的时间
private static final int RETRY_SLEEP_TIME_MILLIS = 1000;
// 网络异常,继续
private static HashSet<Class<?>> exceptionWhitelist = new HashSet<Class<?>>();
// 用户异常,不继续(如,用户中断线程)
private static HashSet<Class<?>> exceptionBlacklist = new HashSet<Class<?>>();

static {
// 以下异常不需要重试,这样异常都是用于造成或者是一些重试也无效的异常
exceptionWhitelist.add(NoHttpResponseException.class);// 连上了服务器但是没有Response
exceptionWhitelist.add(UnknownHostException.class);// host出了问题,一般是由于网络故障
exceptionWhitelist.add(SocketException.class);// Socket问题,一般是由于网络故障
// 以下异常可以重试
exceptionBlacklist.add(InterruptedIOException.class);// 连接中断,一般是由于连接超时引起
exceptionBlacklist.add(SSLHandshakeException.class);// SSL握手失败
}

private final int maxRetries;

public HttpRetry(int maxRetries) {
this.maxRetries = maxRetries;
}

@Override
public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
boolean retry = true;
// 请求是否到达
Boolean b = (Boolean) context.getAttribute(ExecutionContext.HTTP_REQ_SENT);
boolean sent = (b != null && b.booleanValue());

if (executionCount > maxRetries) {
// 尝试次数超过用户定义的测试
retry = false;
} else if (exceptionBlacklist.contains(exception.getClass())) {
// 线程被用户中断,则不继续尝试
retry = false;
} else if (exceptionWhitelist.contains(exception.getClass())) {
// 出现的异常需要被重试
retry = true;
} else if (!sent) {
// 请求没有到达
retry = true;
}
// 如果需要重试
if (retry) {
// 获取request
HttpUriRequest currentReq = (HttpUriRequest) context.getAttribute(ExecutionContext.HTTP_REQUEST);
// POST请求难道就不需要重试?
//retry = currentReq != null && !"POST".equals(currentReq.getMethod());
retry = currentReq != null;
}
if (retry) {
// 休眠1秒钟后再继续尝试
SystemClock.sleep(RETRY_SLEEP_TIME_MILLIS);
} else {
exception.printStackTrace();
}
return retry;
}
}


2.使用
HttpResult httpResult =HttpHelper.get(HttpHelper.URL+"home"+"?index"+index); //http://127.0.0.1:8090/home?index=
String json =httpResult.getString();


3.联网的方式很多,用最适合的

6.把缓存保存到本地

1. 方法:(1)把整个json保存到本地

(2)把解析后的数据保存到本地数据库

2.判断json文件是否过期

(1)MD5比对 加密后的文件与服务器发来的文件加密后对比

(2)在json文件第一行写一个过期时间,对比

3.管理文件的类---工具类 缓存文件一般写在一个单独的文件夹(GooglePlay)中
cache和icon是GooglePlay的子文件夹
cache保存json
icon保存图片
public class FileUtils {
public static final String CACHE = "cache";      //保存json
public static final String ICON = "icon";        //保存图片
public static final String ROOT = "GooglePlay";  //根路径
/**
* 获取图片的缓存的路径
* @return
*/
public static File getIconDir(){
return getDir(ICON);

}
/**
* 获取缓存路径
* @return
*/
public static File getCacheDir() {
return getDir(CACHE);
}
public static File getDir(String cache) {
StringBuilder path = new StringBuilder();  //StringBuilder比String效率要高
if (isSDAvailable()) {                     //如果SD卡可用
path.append(Environment.getExternalStorageDirectory()
.getAbsolutePath());           //sd卡根路径
path.append(File.separator);// '/'
path.append(ROOT);// /mnt/sdcard/GooglePlay
path.append(File.separator);
path.append(cache);// /mnt/sdcard/GooglePlay/cache

}else{                                   //放在程序的cache目录下
File filesDir = UiUtils.getContext().getCacheDir();    //  cache  getFileDir file
path.append(filesDir.getAbsolutePath());// /data/data/com.itheima.googleplay/cache
path.append(File.separator);///data/data/com.itheima.googleplay/cache/
path.append(cache);///data/data/com.itheima.googleplay/cache/cache
}
File file = new File(path.toString());
if (!file.exists() || !file.isDirectory()) {
file.mkdirs();// 创建文件夹
}
return file;

}

private static boolean isSDAvailable() {    //判断SD卡是否可用
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
return true;
} else {
return false;
}
}

}


4.使用:把整个Json数据保存到本地文件中
private void saveLocal(String json, int index) {

BufferedWriter bw = null;
try {
File dir=FileUtils.getCacheDir();
//在第一行写一个过期时间
File file = new File(dir, "home_"+ index); // /mnt/sdcard/googlePlay/cache/home_0			  FileWriter fw = new FileWriter(file);
bw = new BufferedWriter(fw);
bw.write(System.currentTimeMillis() + 1000 * 100 + "");
bw.newLine();// 换行
bw.write(json);// 把整个json文件保存起来
bw.flush();
bw.close();
} catch (Exception e) {
e.printStackTrace();
}finally{
IOUtils.closeQuietly(bw);
}
}


7.读取本地缓存

1.读取本地缓存

private String loadLocal(int index) {
//  如果发现文件已经过期了 就不要再去复用缓存了
File dir=FileUtils.getCacheDir();// 获取缓存所在的文件夹
File file = new File(dir, getKey()+"_" + index);
try {
FileReader fr=new FileReader(file);
BufferedReader br=new BufferedReader(fr);
long outOfDate = Long.parseLong(br.readLine()); //获取过期时间
if(System.currentTimeMillis()>outOfDate){       //与本地时间比较
return null;
}else{
String str=null;
StringWriter sw=new StringWriter();
while((str=br.readLine())!=null){

sw.write(str);
}
return sw.toString();
}

} catch (Exception e) {
e.printStackTrace();
return null;
}
}


8.Json解析

1.不用框架
2. AppInfo 应用程序信息类
public class AppInfo {

private long id;
private String name;
private String packageName;
private String iconUrl;
private float stars;
private long size;
private String downloadUrl;
private String des;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPackageName() {
return packageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public String getIconUrl() {
return iconUrl;
}
public void setIconUrl(String iconUrl) {
this.iconUrl = iconUrl;
}
public float getStars() {
return stars;
}
public void setStars(float stars) {
this.stars = stars;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
public String getDownloadUrl() {
return downloadUrl;
}
public void setDownloadUrl(String downloadUrl) {
this.downloadUrl = downloadUrl;
}
public String getDes() {
return des;
}
public void setDes(String des) {
this.des = des;
}
public AppInfo() {
super();
}
public AppInfo(long id, String name, String packageName, String iconUrl,
float stars, long size, String downloadUrl, String des) {
super();
this.id = id;
this.name = name;
this.packageName = packageName;
this.iconUrl = iconUrl;
this.stars = stars;
this.size = size;
this.downloadUrl = downloadUrl;
this.des = des;
}
@Override
public String toString() {
return "AppInfo [id=" + id + ", name=" + name + ", packageName="
+ packageName + ", iconUrl=" + iconUrl + ", stars=" + stars
+ ", size=" + size + ", downloadUrl=" + downloadUrl + ", des="
+ des + "]";
}

}


3.解析Json
//见到大括号 就用JsonObject ,见到中括号就是JsonArray

private List<AppInfo> paserJson(String json) {
List<AppInfo> appInfos=new ArrayList<AppInfo>();
try {
JSONObject jsonObject=new JSONObject(json);
JSONArray jsonArray = jsonObject.getJSONArray("list");
for(int i=0;i<jsonArray.length();i++){
JSONObject jsonObj = jsonArray.getJSONObject(i);
long id=jsonObj.getLong("id");
String name = jsonObj.getString("name");
String packageName=jsonObj.getString("packageName");
String iconUrl = jsonObj.getString("iconUrl");
float stars=Float.parseFloat(jsonObj.getString("stars"));
long size=jsonObj.getLong("size");
String downloadUrl = jsonObj.getString("downloadUrl");
String des = jsonObj.getString("des");
AppInfo info=new AppInfo(id, name, packageName, iconUrl, stars, size, downloadUrl, des);
appInfos.add(info);
}
return appInfos;

} catch (JSONException e) {
e.printStackTrace();
return null;
}
}


2.HomeFragment 中判断服务器数据

/*
* 校验数据
*/
private LoadResult checkData(List<AppInfo> load){
if(load==null){
return LoadResult.error;
}else{
if(load.size()==0){
return LoadResult.empty;
}else{
return LoadResult.success;
}
}
}
}


9.布局的搭建

<!-- 凡是以layout开头的属性 其实都是经过父容器批准才能生效 因为在listView 中 layout_height 无论写什么熟悉 都是包裹内容 -->

Listview之间分隔
<span style="font-size:14px;"><?xml version="1.0" encoding="utf-8"?>
<!-- 凡是以layout开头的属性 其实都是经过父容器批准才能生效  因为在listView 中 layout_height 无论写什么属性 都是包裹内容 -->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="113dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:background="@drawable/list_item_bg" >

<RelativeLayout
android:id="@+id/item_top"
android:layout_width="match_parent"
android:layout_height="72dp" >

<ImageView
android:id="@+id/item_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_centerVertical="true"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:src="@drawable/ic_default" />

<RelativeLayout
android:id="@+id/item_action"
android:layout_width="70dp"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:gravity="center" >

<FrameLayout
android:id="@+id/action_progress"
android:layout_width="27dp"
android:layout_height="27dp"
android:layout_centerHorizontal="true"
android:background="@drawable/ic_download" />

<TextView
android:id="@+id/action_txt"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/action_progress"
android:layout_marginTop="5dp"
android:ellipsize="end"
android:gravity="center"
android:singleLine="true"
android:textColor="#ff7a7a7a"
android:textSize="12dp"
android:text="下载" />
</RelativeLayout>

<RelativeLayout
android:id="@+id/item_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toLeftOf="@id/item_action"
android:layout_toRightOf="@id/item_icon" >

<TextView
android:id="@+id/item_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textColor="#ff333333"
android:textSize="16dp" />

<RatingBar
android:id="@+id/item_rating"
android:layout_width="wrap_content"
android:layout_height="14dp"
android:layout_below="@id/item_title"
android:layout_marginBottom="2dp"
android:layout_marginTop="2dp"
android:isIndicator="true"
android:progressDrawable="@drawable/process_ratingbar"
android:rating="2.5" />

<TextView
android:id="@+id/item_size"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/item_rating"
android:singleLine="true"
android:textColor="#ff7a7a7a"
android:textSize="12dp" />
</RelativeLayout>
</RelativeLayout>

<View
android:id="@+id/item_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_below="@id/item_top"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:background="@color/item_divider" />

<TextView
android:id="@+id/item_bottom"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_below="@id/item_divider"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:ellipsize="end"
android:gravity="center_vertical"
android:singleLine="true"
android:textColor="#ff717171"
android:textSize="14dp" />
</RelativeLayout>

</FrameLayout></span>


10.加载界面&bitMapUtils的用法

1.ListView优化:ViewHolder

2.查看系统控件的样式 D:\安卓\adt-bundle-windows-x86-20131030\sdk\platforms\android-19\data\res\values

3.RatingBar
和水平进度条非常相似
图层(和帧布局相似)---------重构系统的,放在drawable中
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+android:id/background" android:drawable="@drawable/rating_small_empty" />
<item android:id="@+android:id/secondaryProgress" android:drawable="@drawable/rating_small_half" />
<item android:id="@+android:id/progress" android:drawable="@drawable/rating_small_full" />
</layer-list>


4.加载服务器的图片(三级缓存)
使用BitmapUtil,查看BitmapUtil的例子使用方法,仿照使用例子写代码
BitmapUtils不是单例的 根据需要重载多个获取实例的方法
指定图片缓存路径
(1)使BitmapUtil变成单例,保证bitmapUtil在内存中只存在一份,方便对图片的管理
public class BitmapHelper {
private BitmapHelper() {
}

private static BitmapUtils bitmapUtils;

/**
* BitmapUtils不是单例的 根据需要重载多个获取实例的方法
*
* @param appContext
*            application context
* @return
*/
public static BitmapUtils getBitmapUtils() {
if (bitmapUtils == null) {
// 第二个参数 缓存图片的路径 // 加载图片 最多消耗多少比例的内存 0.05-0.8f
bitmapUtils = new BitmapUtils(UiUtils.getContext(), FileUtils
.getIconDir().getAbsolutePath(), 0.3f);
}
return bitmapUtils;
}
}


(2)使用
BitmapUtils bitmapUtils=BitmapHelper.getBitmapUtils();
//显示图片的控件
bitmapUtils.display(holder.item_icon,Url);//第二个参数为图片完整路径


3.ListView的滑动状态--------(三种状态)
(1)飞速滑动时不需要加载图片
BitmapUtil中的方法
ListView listview = new ListView(Uiutils.getContext());
  listview.setAdapter(new HomeAdapter());
  bitmapUtils=BitmapHelper.getBitmapUtils();
  //第二个参数 慢慢滑动的时候是否加载图片 false 加载 true 不加载
  //第三个参数 飞速滑动的时候是否加载图片 true 不加载
  listview.setOnScrollListener(new PauseOnScrollListener(bitmapUtils,false,true));
  bitmapUtils.configDefaultLoadingImage(R.drawable.ic_default);//设置如果图片加载中显示的图片
  bitmapUtils.configDefaultLoadFailedImage(R.drawable.ic_default);//加载失败显示的图片
<span style="font-size:14px;"> </span>

(2)其他方法见BitMapUtils的例子:bitmapUtilFragment

4.ListView适配器代码

public class HomeAdapter extends BaseAdapter {

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

@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
ViewHolder holder;
if(convertView==null){
view=View.inflate(Uiutils.getContext(), R.layout.item_app, null);
holder=new ViewHolder();
holder.item_icon=(ImageView) view.findViewById(R.id.item_icon);
holder.item_title=(TextView) view.findViewById(R.id.item_title);
holder.item_size=(TextView) view.findViewById(R.id.item_size);
holder.item_bottom=(TextView) view.findViewById(R.id.item_bottom);
holder.item_rating=(RatingBar) view.findViewById(R.id.item_rating);
view.setTag(holder);
}else{
view=convertView;
holder=(ViewHolder) view.getTag();
}
AppInfo appInfo=datas.get(position);
holder.item_title.setText(appInfo.getName());// 设置应用程序的名字
String size=Formatter.formatFileSize(Uiutils.getContext(), appInfo.getSize());
holder.item_size.setText(size);
holder.item_bottom.setText(appInfo.getDes());
float stars = appInfo.getStars();
holder.item_rating.setRating(stars); // 设置ratingBar的值
String iconUrl = appInfo.getIconUrl();  //http://127.0.0.1:8090/image?name=app/com.youyuan.yyhl/icon.jpg
bitmapUtils=BitmapHelper.getBitmapUtils();
// 显示图片的控件
bitmapUtils.display(holder.item_icon, HttpHelper.URL+"image?name="+iconUrl);
return view;
}

@Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return datas.get(arg0);
}

@Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return arg0;
}

}

static class ViewHolder {
ImageView item_icon;
TextView item_title, item_size, item_bottom;
RatingBar item_rating;
}


11.专题界面

1.写一个协议类,操作数据(联网,保存到本地,在本地获取)SubjectProtocol

(1)因为HomeProtocol和SubjectProtocol有共性,所以抽取成父类BaseProtocol

public abstract class BaseProtocol<T> {
public T load(int index) {
// 加载本地数据
String json = loadLocal(index);
if (json == null) {
// 请求服务器
json = loadServer(index);
if (json != null) {
saveLocal(json, index);
}
}
if (json != null) {
return paserJson(json);
} else {
return null;
}
}

private String loadServer(int index) {
HttpResult httpResult = HttpHelper.get(HttpHelper.URL +getKey()
+ "?index=" + index);
String json = httpResult.getString();
return json;
}
private void saveLocal(String json, int index) {

BufferedWriter bw = null;
try {
File dir=FileUtils.getCacheDir();
//在第一行写一个过期时间
File file = new File(dir, getKey()+"_" + index); // /mnt/sdcard/googlePlay/cache/home_0
FileWriter fw = new FileWriter(file);
bw = new BufferedWriter(fw);
bw.write(System.currentTimeMillis() + 1000 * 100 + "");
bw.newLine();// 换行
bw.write(json);// 把整个json文件保存起来
bw.flush();
bw.close();
} catch (Exception e) {
e.printStackTrace();
}finally{
IOUtils.closeQuietly(bw);
}
}

private String loadLocal(int index) {
//  如果发现文件已经过期了 就不要再去复用缓存了
File dir=FileUtils.getCacheDir();// 获取缓存所在的文件夹
File file = new File(dir, getKey()+"_" + index);
try {
FileReader fr=new FileReader(file);
BufferedReader br=new BufferedReader(fr);
long outOfDate = Long.parseLong(br.readLine());
if(System.currentTimeMillis()>outOfDate){
return null;
}else{
String str=null;
StringWriter sw=new StringWriter();
while((str=br.readLine())!=null){

sw.write(str);
}
return sw.toString();
}

} catch (Exception e) {
e.printStackTrace();
return null;
}
}

/**
* 解析json
* @param json
* @return
*/
public abstract T paserJson(String json);
/**
* 说明了关键字
* @return
*/
public abstract String getKey();
}


(2)创建接收对象

public class SubjectInfo {
private String des;
private String url;
public String getDes() {
return des;
}
public void setDes(String des) {
this.des = des;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public String toString() {
return "SubjectInfo [des=" + des + ", url=" + url + "]";
}
public SubjectInfo() {
super();
}
public SubjectInfo(String des, String url) {
super();
this.des = des;
this.url = url;
}

}


(3)SubjectProtocol

public class SubjectProtocol extends BaseProtocol<List<SubjectInfo>>{

@Override
public List<SubjectInfo> paserJson(String json) {
List<SubjectInfo> subjectInfos=new ArrayList<SubjectInfo>();
try {
JSONArray jsonArray=new JSONArray(json);
for(int i=0;i<jsonArray.length();i++){
JSONObject jsonObject = jsonArray.getJSONObject(i);
String des=jsonObject.getString("des");
String url = jsonObject.getString("url");
SubjectInfo info=new SubjectInfo(des, url);
subjectInfos.add(info);

}
return subjectInfos;

} catch (JSONException e) {
e.printStackTrace();
return null;
}
}

@Override
public String getKey() {
return "subject";
}

}


2.把校验数据方法放在父类中BaseFragment

/**
* 校验数据
* @param load
* @return
*/
protected LoadResult checkData(List load) {
if (load == null) {
return LoadResult.error;
} else {
if (load.size() == 0) {
return LoadResult.empty;
} else {
return LoadResult.success;
}
}
}


3.布局



4.布局文件
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="9dip"
android:layout_marginRight="9dip"
android:background="@drawable/list_item_bg" >

<ImageView
android:id="@+id/item_icon"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitCenter"
android:src="@drawable/ic_default"
android:padding="5dp"/>

<TextView
android:id="@+id/item_txt"
style="@style/TitleStyle"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_below="@id/item_icon"
android:gravity="center_vertical"
android:paddingBottom="5dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:singleLine="true" />
</RelativeLayout>

</FrameLayout>


style
<style name="TitleStyle">
<item name="android:textColor">@color/txt_title</item>
<item name="android:textSize">@dimen/list_item_title_size</item>
<item name="android:ellipsize">end</item>
<item name="android:singleLine">true</item>
</style>


5.SubjectFragment
public class SubjectFragment extends BaseFragment {

private List<SubjectInfo> datas;

@Override
public View createSuccessView() {
ListView listView=new ListView(UiUtils.getContext());
listView.setAdapter(new SubjectAdapter());
return listView;
}
private class SubjectAdapter extends BaseAdapter{

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

@Override
public Object getItem(int position) {
return datas.get(position);
}

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

@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
ViewHolder holder;
if(convertView!=null){
view=convertView;
holder=(ViewHolder) view.getTag();
}else{
view=UiUtils.inflate(R.layout.item_subject);
holder=new ViewHolder();
holder.item_icon=(ImageView) view.findViewById(R.id.item_icon);
holder.item_txt=(TextView) view.findViewById(R.id.item_txt);
view.setTag(holder);
}
SubjectInfo info=datas.get(position);
holder.item_txt.setText(info.getDes());
bitmapUtils.display(holder.item_icon, HttpHelper.URL+"image?name="+info.getUrl());
return view;
}

}
class ViewHolder{
ImageView item_icon;
TextView item_txt;
}

@Override
protected LoadResult load() {
SubjectProtocol protocol=new SubjectProtocol();
datas = protocol.load(0);
return checkData(datas);
}
}


12.BaseListView

1.透明图片----nothing
1.ListView
//		setSelector  点击显示的颜色
//		setCacheColorHint  拖拽的颜色
//		setDivider  每个条目的间隔	的分割线
this.setSelector(R.drawable.nothing);  // 什么都没有
this.setCacheColorHint(R.drawable.nothing);
this.setDivider(UiUtils.getDrawalbe(R.drawable.nothing));


2.BaseListView
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: