经验总结:1.开发中不经常使用XML经常使用JSON,开发中要写单独的UNIT单元测试类,单独的工具类封包,开发中bean不要使用私有,要共有,如果使用bean的话或使用反射框架,消耗手机内存 ,安卓开发文档中有明确说明
问题:sharedpreference存储在那个地方,默认的sharedpreference存储在哪,生命周期是什么
1.点击按钮的4中监听方法
1.匿名内部类
2.创建一个类实现OnclickListener,setOnClickListener时传类的一个对象
3.让当前类实现OnclickListener,setOnClickListener时传this,在公司开发中一般用这种方式,用swich判断是哪个按钮
4.在布局文件中为控件添加一个onclick属性,在对应的activity中写一个以onclick属性值为名的方法,记住要 public, 名字对应,参数必须是View类型,内部实现是反射技术。一般开发不用,简单测试时使用.
2.安卓中的常用5大布局
1.线性布局 LinearLayout 垂直和水平 ; 要么从左到右,要么从上到下
padding:当前控件的子控件距离当前控件的长度
margin: 当前控件相对于四周控件或父控件的距离
layout_gravity:当前控件相对于父控件的对其方式
gravity:当前控件中的子控件相对于当前控件的对其方式
2.相对布局 RelativeLayout 要指定每个控件之间的相对位置,否则都从左上角开始布局
layout_above:位于哪个控件的上方
layout_below:位于哪个控件的下方
layout_toRightOf:位于哪个控件的右方
layout_toLeftOf:位于哪个控件的左方
layout_alignParentLeft:位于父窗体的左侧
layout_alignParentRight:
layout_alignParentBottom
layout_alignParentTop:
layout_centerInParent:位于父窗体的中心
layout_alignLeft:与哪个控件的左侧对其
layout_alignRigth:
layout_alignTop
layout_alignBottom
3.帧布局 FrameLayout 一层一层向上叠加布局
4.表格布局 TableLayout
TableLayout中的一个TableRow代表一行,TableRow中的一个控件代表一列
5.绝对布局 (被google抛弃)
3.测试的相关概念
1.按照是否知道代码划分
白盒测试 :知道源码
黑盒测试 :不知道代码
2.按照测试的粒度
a.方法测试
b.单元测试 Junit
c.系统测试
d.集成测试
3.按照测试的暴力程度
a.冒烟测试
b.压力测试 12306
android中的压力测试 : adb shell指令: monkey -p packagename count;
coun表示点击多少下
百度云测:第三方测试平台
4将数据存储到文件中
逻辑步骤:
1.写布局
LinearLayout + RelativeLayout
两个EditText 一个 CheckBox 一个Button
2.写业务逻辑
a.找到所需的控件
b.为按钮设置点击事件监听器
c.在onclick方法中获取用户输入的用户名,密码,是否记住密码
d.判断用户名密码是否为kong,不为空,执行登陆,为null时提示用户
e.执行登陆 (默认登陆成功,省略)
f.判断是否记住密码,记住密码需要将密码保存到本地
g.如果保存的有密码,下次进入程序,需要将用户名密码回显。
***********使用Context对象获取私有目录:/data/data/packagename/files
String path = context.getFilesDir().getPath();
代码:
存储工具类
publicclassStoregeUtil {
Stringpath="/data/data/com.example.day02_login";
publicbooleansavedata(Context con,String name,String psw) {
//TODOAuto-generated method stub
String info=name+"##"+psw;
// FileOutputStream out=new FileOutputStream(new File(path,"info.txt"));
// out.write(info.getBytes());
try{
//使用该方法表示打开一个私有目录的输出流,不需要再确认路径,目录路径为/data/data/com.example.day02_login/file
FileOutputStream out=con.openFileOutput("info.txt", con.MODE_PRIVATE);
out.write(info.getBytes());
returntrue;
}catch(FileNotFoundException e) {
//TODOAuto-generated catch block
e.printStackTrace();
}catch(IOException e) {
//TODOAuto-generated catch block
e.printStackTrace();
}
returnfalse;
}
publicMap getinfo(Context con) {
//TODOAuto-generated method stub
try{
// FileInputStream in=new FileInputStream(new File(path,"info.txt"));
//
FileInputStream in=con.openFileInput("info.txt");
BufferedReader bf=newBufferedReader(newInputStreamReader(in));
String info=bf.readLine();
Map mp=newHashMap();
mp.put("name", info.split("##")[0]);
mp.put("psw", info.split("##")[1]);
returnmp;
}catch(FileNotFoundException e) {
//TODOAuto-generated catch block
e.printStackTrace();
}catch(IOException e) {
//TODOAuto-generated catch block
e.printStackTrace();
}
returnnull;
}
}
主类
publicclassMainActivityextendsActivityimplementsOnClickListener {
EditTextinput_name;
EditTextinput_psw;
CheckBoxcheck_rem;
StoregeUtilutil=newStoregeUtil();
@Override
protectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_index);
// 获取需要的空间id
input_name= (EditText) findViewById(R.id.input_name);
input_psw= (EditText) findViewById(R.id.input_psw);
check_rem= (CheckBox) findViewById(R.id.check_remeberpsw);
Button bt_login = (Button) findViewById(R.id.bt_login);
bt_login.setOnClickListener(this);
Map map=util.getinfo(this);
if(map==null)
{
return;
}else
{
input_name.setText(map.get("name"));
input_psw.setText(map.get("psw"));
check_rem.setChecked(true);
}
}
@Override
publicvoidonClick(View v) {
intm = v.getId();
switch(m) {
caseR.id.bt_login:
String name =input_name.getText().toString().trim();
String string =input_psw.getText().toString();
//注意判断输入是否为空
if(TextUtils.isEmpty(name)||TextUtils.isEmpty(string))
{
Toast.makeText(this,"输入不能为空",0).show();
return;
}
if(check_rem.isChecked())
{
booleanflag=util.savedata(this,name,string);
if(flag)
{
Toast.makeText(this,"保存数据成功",0).show();
}else
{
Toast.makeText(this,"保存数据失败",0).show();
}
}
break;
default:
break;
}
}
}
5将数据存入SD卡
工具类
publicbooleansave(Context con, String name, String psw) {
//开启输出流
String info=name+"##"+psw;
try{
// FileOutputStream out=con.openFileOutput("info", con.MODE_PRIVATE);
//获取SD卡的路径 ,路径为/mnt/sccard/
String path=Environment.getExternalStorageDirectory().getPath();
FileOutputStream out=newFileOutputStream(newFile (path,"info.txt"));
out.write(info.getBytes());
returntrue;
}catch(FileNotFoundException e) {
//TODOAuto-generated catch block
e.printStackTrace();
}catch(IOException e) {
//TODOAuto-generated catch block
e.printStackTrace();
}
returnfalse;
}
publicMap returninfo(Context con) {
//TODOAuto-generated method stub
try{
String path=Environment.getExternalStorageDirectory().getPath();
FileInputStream in=newFileInputStream(newFile (path,"info.txt"));
Map mp=newHashMap();
BufferedReader br=newBufferedReader(newInputStreamReader(in));
mp.put("name",br.readLine().split("##")[0]);
mp.put("psw",br.readLine().split("##")[1]);
returnmp;
}catch(FileNotFoundException e) {
//TODOAuto-generated catch block
e.printStackTrace();
}catch(IOException e) {
//TODOAuto-generated catch block
e.printStackTrace();
}
returnnull;
}
}
主类
publicclassMainActivityextendsActivityimplementsOnClickListener{
SPutilsutil=newSPutils();
privateEditTextet_name;
privateEditTextet_psw;
privateCheckBoxcb_rem;
privateButtonbt_login;
protectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_name= (EditText)findViewById(R.id.et_name);
et_psw= (EditText)findViewById(R.id.et_psw);
cb_rem= (CheckBox)findViewById(R.id.cb_rem);
bt_login= (Button)findViewById(R.id.bt_login);
//注册监听
bt_login.setOnClickListener(this);
if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
{
Toast.makeText(this,"SD卡未能挂载", 0).show();
return;
}
//获取回显的数据
Map mp=util.returninfo(this);
if(mp!=null)
{
et_name.setText(mp.get("name"));
et_psw.setText(mp.get("psw"));
cb_rem.setChecked(true);
return;
}
}
@Override
publicvoidonClick(View v) {
String name=et_name.getText().toString().trim();
String psw=et_psw.getText().toString();
if(TextUtils.isEmpty(name)||TextUtils.isEmpty(psw))
{
Toast.makeText(this,"不能为空", 0).show();
return;
}
//检查SD卡的状态,是否挂载,存储量是否够
if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
{
Toast.makeText(this,"SD卡未能挂载", 0).show();
return;
}
longsize_free=Environment.getExternalStorageDirectory().getFreeSpace();
longsize_usable=Environment.getExternalStorageDirectory().getUsableSpace();
//String size_free1=Formatter.formatFileSize(this, size_free1);
//String size_usable1=Formatter.formatFileSize(this, size_usable1);
//判断存储空间是否足够
//if(size_usable<100*1024*1024)
// {
// Toast.makeText(this, "存储空间不够 为", 0).show();
// return;
// }
if(util.save(this,name,psw))
{
Toast.makeText(this,"成功保存", 0).show();
}else
{
Toast.makeText(this,"没有保存", 0).show();
}
}
6.sharepreference存储数据
SharedPreferences数据是以xml方式存储在data/data/私有目录下的一个shared_pres文件夹下。
SharedPreferences一般用来存放一些标记性的数据,设置性的数据。
工具类
publicclassSPutils {
publicMap returninfo(Context con) {
//TODOAuto-generated method stub
SharedPreferences sh=con.getSharedPreferences("info.txt", con.MODE_PRIVATE);
Map mp=newHashMap();
mp.put("name",sh.getString("name",null));
mp.put("psw",sh.getString("psw",null));
returnmp;
}
publicbooleansave(Context con, String name, String psw) {
//TODOAuto-generated method stub
//获得sharedpreferece
SharedPreferences sh=con.getSharedPreferences("info.txt", con.MODE_PRIVATE);
Editor edit = sh.edit();
edit.putString("name", name);
edit.putString("psw", psw);
//确认写入
if(edit.commit())
{
returntrue;
}else{
returnfalse;}
}
7.xml解析
XML的序列化:
// 备份短信使用XmlSerializer
public static boolean backupSmsForAndroid(Context context,
ArrayList lists) {
try {
// 1.通过Xml类创建一个XmlSerializer对象
XmlSerializer xs = Xml.newSerializer();
// 2.设置XmlSerializer对象将xml写入到哪个文件中。
xs.setOutput(context.openFileOutput("smsbackup2.xml",Context.MODE_PRIVATE), "utf-8");//os:写入到哪个文件流中,encoding:流的编码
// 3.使用XmlSerializer对象序列化一个xml声明头 encoding:xml的编码 standalone:是否独立
xs.startDocument("utf-8", true);
// 4.序列化一个根节点 namespace:命名空间 name:标签的名称
xs.startTag(null, "Smss");
// 5.循环遍历list集合,序列化一条条短信
for (SmsBean smsBean : lists) {
xs.startTag(null, "Sms");
//写一个标签的属性 namespace:命名空间 name:属性的名称 value :属性的值
xs.attribute(null, "id", smsBean.id);
xs.startTag(null, "num");
xs.text(smsBean.num);//写入一个标签的值
xs.endTag(null, "num");
xs.startTag(null, "msg");
xs.text(smsBean.msg);//写入一个标签的值
xs.endTag(null, "msg");
xs.startTag(null, "date");
xs.text(smsBean.date);//写入一个标签的值
xs.endTag(null, "date");
xs.endTag(null, "Sms");
}
// 6.序列化一个根节点的结束节点
xs.endTag(null, "Smss");
// 7.完成xml的写入
xs.endDocument();
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
pull解析XML(反序列化)
//恢复短信
public static int restoreSms(Context context) {
ArrayList lists = null;
SmsBean smsBean = null;
try{
//1.创建一个XmlPullParser对象
XmlPullParser xpp = Xml.newPullParser();
//2.设置要解析的文件的流 in :读取流 encoding:流的编码
xpp.setInput(context.openFileInput("smsbackup2.xml"),"utf-8");
//3.获取xml第一行的事件类型
int type = xpp.getEventType();
//4.循环判断事件类型是否文档结束
while (type!= XmlPullParser.END_DOCUMENT) {
String currentTagName = xpp.getName(); //获取当前标签的名称
//5.不是文档结束,判断是开始标签还是结束标签,解析每一行的内容以bean的方式封装到list集合中,并且获取下一行事件 的类型。
switch (type) {
case XmlPullParser.START_TAG:
if("Smss".equals(currentTagName)){
//初始化一个list集合
lists = new ArrayList();
}else if("Sms".equals(currentTagName)){
//初始化一个SmsBean对象,并解析出id
smsBean = new SmsBean();
smsBean.id = xpp.getAttributeValue(null, "id");
}else if("num".equals(currentTagName)){
smsBean.num = xpp.nextText();//获取内容
}else if("msg".equals(currentTagName)){
smsBean.msg = xpp.nextText();//获取内容
}else if("date".equals(currentTagName)){
smsBean.date = xpp.nextText();//获取内容
}
break;
case XmlPullParser.END_TAG:
//当前标签是结束标签并且是sms那么就将bean对象添加到list集合中
if ("Sms".equals(currentTagName)) {
lists.add(smsBean);
}
break;
default:
break;
}
//获取下一行的事件类型
type = xpp.next();
}
//6.返回集合的size就是成功恢复的条数
return lists.size();
}catch (Exception e) {
e.printStackTrace();
}
return 0;
}