本帖最后由 小鲁哥哥 于 2017-6-4 11:18 编辑
【济南中心】Android课程同步笔记智慧北京:Day05(上)
缓存工具类 保存: 从服务器获取数据,把数据保存到/data/data/packagename/files文件中, 以这次请求的url通过md5加密之后作为唯一的文件名,保存到本地
读取: 通过md5加密之后的文件名,从本地读取文件,转换为json数据。
保存数据 [Java] 纯文本查看 复制代码 //缓存json
public static void saveCache(Context context,String url,String json) throws Exception{
//文件名
String name = Md5Utils.encode(url);
//输出流
FileOutputStream fileOutputStream = context.openFileOutput(name, Context.MODE_PRIVATE);
//写数据
fileOutputStream.write(json.getBytes());
//关流
fileOutputStream.close();;
} 读取数据 [Java] 纯文本查看 复制代码 //读取json
public static String readCache(Context context,String url)throws Exception{
//文件名
String name = Md5Utils.encode(url);
FileInputStream fileInputStream = context.openFileInput(name);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while((len = fileInputStream.read(buffer)) != -1){
bos.write(buffer,0,len);
}
String json = bos.toString();
bos.close();
fileInputStream.close();
return json;
} 缓存网络数据 新闻中心模块缓存处理 加载数据成功: 组图模块缓存数据
加载数据成功以后缓存数据: 加载数据失败读取缓存数据: 轮播图模块
成功: 失败:
切换Tab页面避免重新加载数据
默认情况下:MainActivity中,每次切换tab都会加载数据。如下代码: [Java] 纯文本查看 复制代码 @Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
int item = 0;
switch (checkedId){
case R.id.rb_home:
item = 0;
slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_NONE);//无法滑出侧滑菜单
break;
case R.id.rb_newscener:
item = 1;
slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
break;
case R.id.rb_smartservice:
item = 2;
slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
break;
case R.id.rb_govaffairs:
item = 3;
slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
break;
case R.id.rb_setting:
item = 4;
slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_NONE);
break;
}
//让上面的ViewPager切换到对应的页面
tabVp.setCurrentItem(item,false);
//加载网络数据的入口
BaseFragment baseFragment = (BaseFragment) fragments.get(item);
if(baseFragment instanceof BaseLoadNetDataOperator){
((BaseLoadNetDataOperator) baseFragment).loadNetData();
}
}
禁止每次都去加载数据
在我们每个Fragment的父类BaseFragment,定义个boolean类型的标示默认为false,当数据加载成功以后,设置true,在baseFragment定义一个标示: [Java] 纯文本查看 复制代码 public boolean hasLoadData;
[align=left] 在对应的Fragment中,成功加载数据以后,把hasLoadData设置为true; 比如:新闻中心的Fragment:NewsCenterFragment 在MainAcitivity添加是否加载过网络数据的标示判断
[Java] 纯文本查看 复制代码 //获取到对应的Fragment页面
BaseFragment baseFragment = (BaseFragment) fragments.get(item);
if(baseFragment instanceof BaseLoadNetDataOperator && !baseFragment.hasLoadData){
BaseLoadNetDataOperator baseLoadNetDataOperator = (BaseLoadNetDataOperator) baseFragment;
baseLoadNetDataOperator.loadNetData();
}
切换多个Fragment时, NewsCenterFragment无法正常加载数据由于ViewPager有预加载机制。默认它会预加载三个Fragment,如果超出了,就会回收之前创建的Fragment始终保留三个Fragment。需要给ViewPager缓存5个页面。在我们的MainActivity中的initViewpager方法中:设置缓存5个界面。 注意:ViewPager的setOffscreenPageLimit(5),如果指定的数值为5,ViewPager会缓存当前Fragment左右各5Fragment。这是ViewPager的预加载机制。
给新闻条目添加点击事件在我们的NewsListAdapter类中onBindViewHolder,处理点击事件: [Java] 纯文本查看 复制代码 //条目点击事件
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//跳转到新闻详情界面
Intent intent = new Intent(context,NewsDetailActivity.class);
intent.putExtra("url",newsBean.url);
context.startActivity(intent);
}
}); 创建NewsDeatailActiity
布局实现
[XML] 纯文本查看 复制代码 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/title_red_bg">
<ImageButton
android:id="@+id/ib_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/back"
android:layout_marginLeft="10dp"
android:layout_centerVertical="true"/>
<ImageButton
android:id="@+id/ib_textsize"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/icon_textsize"
android:layout_toLeftOf="@+id/ib_share"
android:layout_marginRight="5dp"
android:layout_centerVertical="true"/>
<ImageButton
android:id="@+id/ib_share"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/icon_share"
android:layout_alignParentRight="true"
android:layout_marginRight="10dp"
android:layout_centerVertical="true"/>
</RelativeLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent"></WebView>
<ProgressBar
android:id="@+id/pb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminateDrawable="@drawable/pb_bg"
android:layout_gravity="center"/>
</FrameLayout>
</LinearLayout>
加载显示新闻详情
WebView加载网页结束,隐藏进度条
让WebView支持js脚本
修改Webview字体的大小 创建对话框,让用户去选择字体的大小初始化字体型号数组
[Java] 纯文本查看 复制代码 private String[] types = new String[]{
"超大号字体",
"大号字体",
"正常字体",
"小号字体",
"超小号字体",
};
private WebSettings.TextSize[] textSizes = new WebSettings.TextSize[]{
WebSettings.TextSize.LARGEST,
WebSettings.TextSize.LARGER,
WebSettings.TextSize.NORMAL,
WebSettings.TextSize.SMALLER,
WebSettings.TextSize.SMALLEST,
};
创建对话框,并弹出对话框
选择字体型号,修改网页字体大小
ShareSdk分享
ShareSDK使用1. 下载ShareSDK 2. 运行SDK工具,生成项目包,进行覆盖 3. 查看Android文档 4. 创建应用, 生成appkey,替换项目中的appkey 5. 拷贝相关权限和代码 6. 注意sdcard根目录下需要有test.jpg这张图片,否则会分享失败 7. 运行程序,进行测试 8. 可以修改主题样式 启动分享功能
[Java] 纯文本查看 复制代码 private void showShare() {
ShareSDK.initSDK(this);
OnekeyShare oks = new OnekeyShare();
//关闭sso授权
oks.disableSSOWhenAuthorize();
// 分享时Notification的图标和文字 2.5.9以后的版本不调用此方法
//oks.setNotification(R.drawable.ic_launcher, getString(R.string.app_name));
// title标题,印象笔记、邮箱、信息、微信、人人网和QQ空间使用
oks.setTitle("黑马程序员分享的");
// titleUrl是标题的网络链接,仅在人人网和QQ空间使用
oks.setTitleUrl("http://sharesdk.cn");
// text是分享文本,所有平台都需要这个字段
oks.setText("我是黑马程序员,我骄傲!");
//分享网络图片,新浪微博分享网络图片需要通过审核后申请高级写入接口,否则请注释掉测试新浪微博
oks.setImageUrl("http://f1.sharesdk.cn/imgs/2014/02/26/owWpLZo_638x960.jpg");
// imagePath是图片的本地路径,Linked-In以外的平台都支持此参数
//oks.setImagePath("/sdcard/test.jpg");//确保SDcard下面存在此张图片
// url仅在微信(包括好友和朋友圈)中使用
oks.setUrl("http://sharesdk.cn");
// comment是我对这条分享的评论,仅在人人网和QQ空间使用
oks.setComment("我是测试评论文本");
// site是分享此内容的网站名称,仅在QQ空间使用
oks.setSite(getString(R.string.app_name));
// siteUrl是分享此内容的网站地址,仅在QQ空间使用
oks.setSiteUrl("http://sharesdk.cn");
// 启动分享GUI
oks.show(this);
}
自定义分享来源在资产目录下,进行文件配置渠道来源: [XML] 纯文本查看 复制代码 <ShareSDK
AppKey = "17965efb617e6"/> <!-- 修改成你在sharesdk后台注册的应用的appkey"-->
<!-- ShareByAppClient标识是否使用微博客户端分享,默认是false -->
<SinaWeibo
Id="1"
SortId="1"
AppKey="568898243"
AppSecret="38a4f8204cc784f81f9f0daaf31e02e3"
RedirectUrl="http://www.sharesdk.cn"
ShareByAppClient="true"
Enable="true" /> 点击的新闻条目变灰
点击条目变化的原理点击新闻条目时: l 获取该条目新闻的唯一ID: l 从sp中得到存储的多个新闻ID的字符串 l 判断字符串是否包含该新闻ID n 不包含,存储到sp中,刷新界面,更改选中条目的样式 n 如果存在,直接跳转到新闻详情页 点击条目的处理代码实现: [Java] 纯文本查看 复制代码 //条目点击事件
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//跳转到新闻详情界面
Intent intent = new Intent(context,NewsDetailActivity.class);
intent.putExtra("url",newsBean.url);
context.startActivity(intent);
//存储该条新闻的唯一标识:
String id = newsBean.id;
//存储在哪里?Sp File DB()
String readNews = SPUtils.getString(context, Constant.KEY_HAS_READ,"");
if(!readNews.contains(id)){
String value = readNews+ "," + id;
//存储
SPUtils.saveString(context,Constant.KEY_HAS_READ,value);
//刷新界面
//notifyDataSetChanged();
viewHolder.tvTitle.setTextColor(Color.GRAY);
}
}
});
} 显示新闻列表时,判断是否已经查看过
[Java] 纯文本查看 复制代码 //判断每条新闻是否已经被查看过,如果查看,修改字体样式为灰色
String readNewsContent = SPUtils.getString(context, Constant.KEY_HAS_READ,"");
if(readNewsContent.contains(newsBean.id)){
viewHolder.tvTitle.setTextColor(Color.GRAY);
}else{
viewHolder.tvTitle.setTextColor(Color.BLACK);
}
在新闻中心子tab的切换会多出轮播图bug修复 修改多次添加轮播图到头布局中的问题
拽下轮播图后轮播图停止切换的bug修复
下拉加载数据完成以后,手动开始轮播图进行轮播
注意:这里不管加载失败和加载成功,都要手动的开启轮播图进行轮播图
三级缓存的概念 一级缓存:内存缓存 当去加载图片时,首先从内存缓存,查找图片: 有:直接显示图片 没有:从二级缓存中查找图片 二级缓存:磁盘缓存 一级缓存没有,从二级缓存中查找 有:先保存内存缓存中,然后显示图片 没有:从三级缓存中获取图片。 三级缓存:网络缓存 二级缓存没有图片,从网络缓存中取出图片 有,磁盘缓存,内存缓存 没有,网络获取图片,然后磁盘缓存,内存缓存,显示图片
网络缓存加载图片 编写网络缓存工具类
[Java] 纯文本查看 复制代码 NetCacheUtils:
public class NetCacheUtils {
private static final String TAG = "NetCacheUtils";
private Context context;
//从网络获取图片
public void getBitmapFromNet(Context context,ImageView iv, String url){
this.context = context;
//异步操作
new BitmapTask().execute(iv,url);
}
//异步任务
class BitmapTask extends AsyncTask<Object,Void,Bitmap>{
private ImageView iv;
private String url;
@Override
protected Bitmap doInBackground(Object... params) {
//获取参数
iv = (ImageView) params[0];
url = (String) params[1];
//下载图片
Bitmap bitmap = downloadBitmap(url);
MyLogger.i(TAG,"从网络上加载了图片");
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
//获取ImageView对应的url
String url = (String) iv.getTag();
if(bitmap != null && this.url.equals(url)){
iv.setImageBitmap(bitmap);
}
}
}
//下载图片
private Bitmap downloadBitmap(String url) {
Bitmap bitmap = null;
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection) new URL(url).openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(3000);
conn.setReadTimeout(6000);
conn.connect();
int responseCode = conn.getResponseCode();
if(responseCode == 200){
InputStream inputStream = conn.getInputStream();
//把流转换成Bitmap对象
bitmap = BitmapFactory.decodeStream(inputStream);
return bitmap;
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(conn != null){
conn.disconnect();
}
}
return bitmap;
}
}
异步任务加载网络图片
[Java] 纯文本查看 复制代码 //异步任务
class BitmapTask extends AsyncTask<Object,Void,Bitmap>{
private ImageView iv;
private String url;
@Override
protected Bitmap doInBackground(Object... params) {
//获取参数
iv = (ImageView) params[0];
url = (String) params[1];
//下载图片
Bitmap bitmap = downloadBitmap(url);
MyLogger.i(TAG,"从网络上加载了图片");
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
//获取ImageView对应的url
String url = (String) iv.getTag();
if(bitmap != null && this.url.equals(url)){
iv.setImageBitmap(bitmap);
}
}
}
网络加载图片
[Java] 纯文本查看 复制代码 //下载图片
private Bitmap downloadBitmap(String url) {
Bitmap bitmap = null;
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection) new URL(url).openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(3000);
conn.setReadTimeout(6000);
conn.connect();
int responseCode = conn.getResponseCode();
if(responseCode == 200){
InputStream inputStream = conn.getInputStream();
//把流转换成Bitmap对象
bitmap = BitmapFactory.decodeStream(inputStream);
return bitmap;
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(conn != null){
conn.disconnect();
}
}
return bitmap;
}
执行异步任务
[Java] 纯文本查看 复制代码 //从网络获取图片
public void getBitmapFromNet(Context context,ImageView iv, String url){
this.context = context;
//异步操作
new BitmapTask().execute(iv,url);
}
网络缓存加载图片-图片错位
解决图片错误问题:给imageview设置一个tag
[Java] 纯文本查看 复制代码 //从网络获取图片
public void getBitmapFromNet(Context context,ImageView iv, String url){
this.context = context;
//让ImageView和url关联起来
iv.setTag(url);
//异步操作
new BitmapTask().execute(iv,url);
}
显示图片时,对比URL地址
[Java] 纯文本查看 复制代码 @Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
//获取ImageView对应的url
String url = (String) iv.getTag();
if(bitmap != null && this.url.equals(url)){
iv.setImageBitmap(bitmap);
}
}
磁盘缓存 写缓存到磁盘
[Java] 纯文本查看 复制代码 //写缓存
public static void saveCache(Context context,Bitmap bitmap, String url){
//缓存目录
File dir = new File(context.getCacheDir(),"zhbj_cache");
if(!dir.exists()){
dir.mkdirs();
}
//把图片缓存在缓存目录
File file = new File(dir, Md5Utils.encode(url));
FileOutputStream stream = null;
try {
stream = new FileOutputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
bitmap.compress(Bitmap.CompressFormat.JPEG,100,stream);
}
从磁盘中读缓存
[Java] 纯文本查看 复制代码 //写缓存
public static void saveCache(Context context,Bitmap bitmap, String url){
//缓存目录
File dir = new File(context.getCacheDir(),"zhbj_cache");
if(!dir.exists()){
dir.mkdirs();
}
//把图片缓存在缓存目录
File file = new File(dir, Md5Utils.encode(url));
FileOutputStream stream = null;
try {
stream = new FileOutputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
bitmap.compress(Bitmap.CompressFormat.JPEG,100,stream);
}
修改网络缓存逻辑当从网络中获取图片,应该缓存到磁盘中 [Java] 纯文本查看 复制代码 class BitmapTask extends AsyncTask<Object,Void,Bitmap>{
private ImageView iv;
private String url;
@Override
protected Bitmap doInBackground(Object... params) {
//获取参数
iv = (ImageView) params[0];
url = (String) params[1];
//下载图片
Bitmap bitmap = downloadBitmap(url);
MyLogger.i(TAG,"从网络上加载了图片");
//执行磁盘缓存
LocalCacheUtils.saveCache(context,bitmap,url);
//把数据缓存在内存中
MemoryCacheUtils.saveCache(bitmap,url);
return bitmap;
} 内存缓存 写入内存
从内存读
修改图片加载工具类
[Java] 纯文本查看 复制代码 public class BitmapUtils {
private static final String TAG = "BitmapUtils";
static{
netCacheUtils = new NetCacheUtils();
localCacheUtils = new LocalCacheUtils();
memoryCacheUtils = new MemoryCacheUtils();
}
private static NetCacheUtils netCacheUtils;
private static LocalCacheUtils localCacheUtils;
private static MemoryCacheUtils memoryCacheUtils;
//显示图片
public static void display(Context context,ImageView iv, String url){
Bitmap bitmap = null;
//内存缓存
bitmap = memoryCacheUtils.readCache(url);
if(bitmap != null){
iv.setImageBitmap(bitmap);
MyLogger.i(TAG,"从内存获取了图片");
return;
}
//磁盘缓存
bitmap = localCacheUtils.readCache(context, url);
if(bitmap != null){
iv.setImageBitmap(bitmap);
MyLogger.i(TAG,"从磁盘获取了图片");
return;
}
//网络缓存
netCacheUtils.getBitmapFromNet(context,iv,url);
}
}
|