谷歌应用市场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优化:ViewHolder2.查看系统控件的样式 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.透明图片----nothing1.ListView
// setSelector 点击显示的颜色 // setCacheColorHint 拖拽的颜色 // setDivider 每个条目的间隔 的分割线 this.setSelector(R.drawable.nothing); // 什么都没有 this.setCacheColorHint(R.drawable.nothing); this.setDivider(UiUtils.getDrawalbe(R.drawable.nothing));
2.BaseListView
相关文章推荐
- UVA_10739_StringToPalindrome
- hdu5381The sum of gcd
- C#子线程中更新ui
- Codeforces Round #303 (Div. 2) - E. Paths and Trees(最短路)
- iOS UIAppearance使用详解
- 使用SeekBar监听图片的缩放情况
- 修复OpenStack-Horizon遇到的UnicodeDecodeError
- 初触Python,关于pyquery解析html(百度贴吧)
- 关东升的《从零开始学Swift》即将出版
- 产品中非常重要的 Alpha版本
- elasticsearch 笔记
- Android Hook神器:XPosed入门与登陆劫持演示
- MIME 参考手册
- Yii中POS和GET并用范例
- 分享一种最简单的Android打渠道包的方法
- IBM X3650 M/T 7979 安装WIN2012 R2
- systemd详解
- poj 1675 Happy Birthday!
- Solr查询时设置字段的boost值,改变默认打分排序
- HDU 1394----Minimum Inversion Number