研究cache和file的区别:
这个clear data对应就是清空我们的app当中的files目录中的数据。
而这个clear cache就对应的是我们的app当中的cache目录当中的数据
一般的用户都知道这个clear cache,所以一般情况下一些不重要的数据就放在这个cache目录中,如果是一些重要的数据就放入到files目录当中,因为用户会选择清空这个缓存,所以一般情况下就会把重要的数据放入到我们的files目录下,以防数据loss
以下是我们的两个按键的操作代码如下:
// 这个是我们的点击文件操作的点击事件
public void fileClick(View v) {
// 当我们点击这个按键时就往我们的这个默认的files目录当中进行写入一些数据
// 得到这个当前应用程序当前的文本文件的操作的目录
try {
FileOutputStream fos = openFileOutput("info.txt", MODE_APPEND);
fos.write("word".getBytes());
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
// 这个是我们的点击cache操作的点击事件
public void cacheClick(View v) {
try {
// 当我们点击这个按键时就往我们的这个默认的cache目录当中进行写入一些数据
File f = new File(getCacheDir(), "info.txt");
OutputStream fos = new FileOutputStream(f);
fos.write("hello".getBytes());
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
RunOnUiThread()方法的作用:
如果想要单单是为了在子线程当中更新UI,同时又不想使用Handler对象来来发送信息来完成,那么就是使用这个RunOnUiThread(Runnable)方法来进行操作
RunOnUiThread(Runnable)的介绍如下:
不管是在子线程还是在Ui(main)线程调用到这个API方法,他都表示把这个方法当中的Runnable对象运行在主线程当中,那么我们的这个Ui也就是可以进行更新了
package com.hailong.basemodel;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import com.hailong.ImageLookTest.R;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.ActionBarActivity;
import android.util.Base64;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
public class MainActivity extends ActionBarActivity {
private EditText et;
private ImageView iv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 先找到控件
et = (EditText) findViewById(R.id.ev);
iv = (ImageView) findViewById(R.id.iv);
}
// 开始实现这个按键中的点击方法
public void click(View v) {
// 因为这个是一个网络的为了读写的操作,所以要重新开启一个新的线程来运行操作
new Thread() {
public void run() {
try {
// 先得得图片中的具体的路径
String path = et.getText().toString().trim();
// 创建一个缓存文件,用getCacheDir可以得到这个缓存目录,然后在我们的目录下存储这个文件
File cacheFile = new File(getCacheDir(),Base64.encodeToString(path.getBytes(),Base64.DEFAULT));
if (cacheFile.exists() && cacheFile.length() > 0) {
// 说明这个表示不是第一次请求,已经在我们的本场中已经有了这个请求文件的内容了
// 进行读取这个缓存文件中的内容,也就是文件转换成一个位图类型的数据
final Bitmap cachebitmap = BitmapFactory.decodeFile(cacheFile.getAbsolutePath());
runOnUiThread(new Runnable() {
@Override
public void run() {
iv.setImageBitmap(cachebitmap);
}
});
} else {
// 说明是第一次消息
// 创建一个URI地址,用来封装我们请求的图片地址
URL url = new URL(path);
// 然后用这个URL地址来创建我们的RULConnection对象
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
// 给我们的Connection对象进行设置越时时间和请求方式
// 一般为5s,因为在android系统中如果时间超过了5s,那么就会出现EXecution
conn.setConnectTimeout(5000);
// 设置一下请求的方式
conn.setRequestMethod("GET");// 这个默认就是GET方式
// 然后得到我们的服务器返回的请求状态码,用来判断一下我们的请求是否成功
int code = conn.getResponseCode();
if (code == 200) {
// 如果请求成功,那么就拿到服务器返回来的数据
InputStream in = conn.getInputStream();
// 现在对我们的数据进行缓存的操作
OutputStream ot = new FileOutputStream(cacheFile);
// 进行把我们的服务器返回给我们的数据全部保存在我们的缓存文件当中
int len = -1;
byte[] buffer = new byte[4096];
while ((len = in.read(buffer)) != -1) {
// 把这个缓存当中的文件写入到缓存文件当中
ot.write(buffer, 0, len);
}
// 当我们的数据全部写完之后要进行关流的操作
ot.close();
in.close();// 因为下面的流要关闭了,所以这个流就不能用了,要进行读取这个缓存上目录当中的数据
// 因为是一个图片,在Android中这个图片是用位图来表示,这个位图对应的类是BitMap
// 创建一个位图,用的是位图中的工厂方法来创建这个位图,这个工厂方法中全部都是一个静态的方法
// Bitmap bitmap=BitmapFactory.decodeStream(in);内部类调用了外部类的成员,那么这个成员要加上这个final关键字
final Bitmap bitmap = BitmapFactory.decodeFile(cacheFile.getAbsolutePath());
//这个方法表示把这个Runnable对象放入到这个消息队列当中,同时如果这个Runnable对象一但
//放入到消息队列,那么我们的主线程当中的Looper对象就会取出这个消息,然后交给我们的Handler来处理
runOnUiThread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
iv.setImageBitmap(bitmap);
}
});
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start();
}
}
小细节:当内部类调用了外部类的成员时,这个外部类的成员要加上final关键字以改变这个成员的生成周期
使用runOnUiThread()方法的应用场景如下:
如果单单是为了更新这个UI的话,那么则可以runOnUiThread()这个方法,因为这个方法的操作比较的方便
如果我们的还要向主线程发送数据的话,那么这个runOnUiThread()就做不到了,那么则就只能是使用Handler的api来进行发送信息了
Handler中的常用的api和Timer的区别如下:
package com.hailong.basemodel;
import java.util.Timer;
import java.util.TimerTask;
import com.hailong.handler.R;
import android.os.Bundle;
import android.os.Handler;
//好像这个v7会创建出二个文件
import android.support.v7.app.ActionBarActivity;
import android.widget.Button;
public class MainActivity extends ActionBarActivity {
private Timer time=null;
Button but;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
but=(Button) findViewById(R.id.button1);
//创建一个Handler对象,同时这个postDelayed方法也表示推迟5s后再执行穿上Runnable中的run方法,这个方法有点像我们的Java
//基础的中的定时器对象Timer
// new Handler(){
//
// }.postDelayed(new Runnable() {
//
// @Override
// public void run() {
System.out.println("hehe-----------");
// but.setText("handler");
// }
// },5000);
//用我们的Timer中的基础的方法来执行这个相同的操作,看我们的Java的文档可知,这个方法的是在我们的后台进行当中
//创建出一个定时器对象
time=new Timer();
//这个定时器中也重要的也就是二个方法,一个调度方法scheduler,这个方法有很多的实现,另一个是取消方法
time.schedule(new TimerTask() {
//表示的是把这个方法在5s在后台进程当中进行运行这个Run方法
@Override
public void run() {
// System.out.println("hello world---");
but.setText("handler");
}
},5000);
//这个TimerApi的Scheduler方法的重载操作如下:这个方法表示在3s后就每隔1s就在我们的后台进程当中执行这个TimerTask方法中的run方法
// time.schedule(new TimerTask() { //TimerTask也是一个子线程类
//
// @Override
// public void run() {
// // TODO Auto-generated method stub
// System.out.println("hello world---");
//
// }
// },3000,1000);
}
//定时器和我们的postDelayed方法的区别操作
//在我们的Handler的postDelayed的操作Runnable的run方法中可以进行我我们的更新操作,因为这个Handler方法就是在Mian线程中更新的
//但是在我们的Timer线程不能进行更新我们的UI,因为这个TimerTask也是一个子线程
//当我们的Activity结束时,就会自动的调用下面的这个方法,也就是Activity的生命周期方法
@Override
protected void onDestroy() {
//进行停止我们的Timer定时器中的后台方法的调用操作
time.cancel();
super.onDestroy();
}
}
上面这个在Timer中的run()方法中操作更新这个UI会出现如下的错误:
这个错误的因为是我们的在子线程当中更新了UI控件导致的