經(jīng)驗(yàn)總結(jié):1.開發(fā)中不經(jīng)常使用XML經(jīng)常使用JSON,開發(fā)中要寫單獨(dú)的UNIT單元測(cè)試類,單獨(dú)的工具類封包莱没,開發(fā)中bean不要使用私有,要共有酷鸦,如果使用bean的話或使用反射框架饰躲,消耗手機(jī)內(nèi)存 ,安卓開發(fā)文檔中有明確說明
問題:sharedpreference存儲(chǔ)在那個(gè)地方臼隔,默認(rèn)的sharedpreference存儲(chǔ)在哪嘹裂,生命周期是什么
1.點(diǎn)擊按鈕的4中監(jiān)聽方法
1.匿名內(nèi)部類
2.創(chuàng)建一個(gè)類實(shí)現(xiàn)OnclickListener,setOnClickListener時(shí)傳類的一個(gè)對(duì)象
3.讓當(dāng)前類實(shí)現(xiàn)OnclickListener,setOnClickListener時(shí)傳this,在公司開發(fā)中一般用這種方式摔握,用swich判斷是哪個(gè)按鈕
4.在布局文件中為控件添加一個(gè)onclick屬性寄狼,在對(duì)應(yīng)的activity中寫一個(gè)以onclick屬性值為名的方法,記住要 public, 名字對(duì)應(yīng),參數(shù)必須是View類型氨淌,內(nèi)部實(shí)現(xiàn)是反射技術(shù)泊愧。一般開發(fā)不用,簡單測(cè)試時(shí)使用.
2.安卓中的常用5大布局
1.線性布局 LinearLayout 垂直和水平 ; 要么從左到右盛正,要么從上到下
padding:當(dāng)前控件的子控件距離當(dāng)前控件的長度
margin: 當(dāng)前控件相對(duì)于四周控件或父控件的距離
layout_gravity:當(dāng)前控件相對(duì)于父控件的對(duì)其方式
gravity:當(dāng)前控件中的子控件相對(duì)于當(dāng)前控件的對(duì)其方式
2.相對(duì)布局 RelativeLayout 要指定每個(gè)控件之間的相對(duì)位置删咱,否則都從左上角開始布局
layout_above:位于哪個(gè)控件的上方
layout_below:位于哪個(gè)控件的下方
layout_toRightOf:位于哪個(gè)控件的右方
layout_toLeftOf:位于哪個(gè)控件的左方
layout_alignParentLeft:位于父窗體的左側(cè)
layout_alignParentRight:
layout_alignParentBottom
layout_alignParentTop:
layout_centerInParent:位于父窗體的中心
layout_alignLeft:與哪個(gè)控件的左側(cè)對(duì)其
layout_alignRigth:
layout_alignTop
layout_alignBottom
3.幀布局 FrameLayout 一層一層向上疊加布局
4.表格布局 TableLayout
TableLayout中的一個(gè)TableRow代表一行,TableRow中的一個(gè)控件代表一列
5.絕對(duì)布局 (被google拋棄)
3.測(cè)試的相關(guān)概念
1.按照是否知道代碼劃分
白盒測(cè)試 :知道源碼
黑盒測(cè)試 :不知道代碼
2.按照測(cè)試的粒度
a.方法測(cè)試
b.單元測(cè)試 Junit
c.系統(tǒng)測(cè)試
d.集成測(cè)試
3.按照測(cè)試的暴力程度
a.冒煙測(cè)試
b.壓力測(cè)試 12306
android中的壓力測(cè)試 : adb shell指令: monkey -p packagename count;
coun表示點(diǎn)擊多少下
百度云測(cè):第三方測(cè)試平臺(tái)
4將數(shù)據(jù)存儲(chǔ)到文件中
邏輯步驟:
1.寫布局
LinearLayout + RelativeLayout
兩個(gè)EditText 一個(gè) CheckBox 一個(gè)Button
2.寫業(yè)務(wù)邏輯
a.找到所需的控件
b.為按鈕設(shè)置點(diǎn)擊事件監(jiān)聽器
c.在onclick方法中獲取用戶輸入的用戶名豪筝,密碼腋腮,是否記住密碼
d.判斷用戶名密碼是否為kong,不為空,執(zhí)行登陸壤蚜,為null時(shí)提示用戶
e.執(zhí)行登陸 (默認(rèn)登陸成功,省略)
f.判斷是否記住密碼,記住密碼需要將密碼保存到本地
g.如果保存的有密碼徊哑,下次進(jìn)入程序袜刷,需要將用戶名密碼回顯。
***********使用Context對(duì)象獲取私有目錄:/data/data/packagename/files
String path = context.getFilesDir().getPath();
代碼:
存儲(chǔ)工具類
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{
//使用該方法表示打開一個(gè)私有目錄的輸出流莺丑,不需要再確認(rèn)路徑著蟹,目錄路徑為/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,"保存數(shù)據(jù)成功",0).show();
}else
{
Toast.makeText(this,"保存數(shù)據(jù)失敗",0).show();
}
}
break;
default:
break;
}
}
}
5將數(shù)據(jù)存入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);
//注冊(cè)監(jiān)聽
bt_login.setOnClickListener(this);
if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
{
Toast.makeText(this,"SD卡未能掛載", 0).show();
return;
}
//獲取回顯的數(shù)據(jù)
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卡的狀態(tài),是否掛載梢莽,存儲(chǔ)量是否夠
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);
//判斷存儲(chǔ)空間是否足夠
//if(size_usable<100*1024*1024)
//?????????{
//??????????????Toast.makeText(this, "存儲(chǔ)空間不夠???? 為", 0).show();
//??????????????return;
//?????????}
if(util.save(this,name,psw))
{
Toast.makeText(this,"成功保存", 0).show();
}else
{
Toast.makeText(this,"沒有保存", 0).show();
}
}
6.sharepreference存儲(chǔ)數(shù)據(jù)
SharedPreferences數(shù)據(jù)是以xml方式存儲(chǔ)在data/data/私有目錄下的一個(gè)shared_pres文件夾下萧豆。
SharedPreferences一般用來存放一些標(biāo)記性的數(shù)據(jù),設(shè)置性的數(shù)據(jù)昏名。
工具類
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);
//確認(rèn)寫入
if(edit.commit())
{
returntrue;
}else{
returnfalse;}
}
7.xml解析
XML的序列化:
// 備份短信使用XmlSerializer
public static boolean backupSmsForAndroid(Context context,
ArrayList lists) {
try {
// 1.通過Xml類創(chuàng)建一個(gè)XmlSerializer對(duì)象
XmlSerializer xs = Xml.newSerializer();
// 2.設(shè)置XmlSerializer對(duì)象將xml寫入到哪個(gè)文件中涮雷。
xs.setOutput(context.openFileOutput("smsbackup2.xml",Context.MODE_PRIVATE), "utf-8");//os:寫入到哪個(gè)文件流中,encoding:流的編碼
// 3.使用XmlSerializer對(duì)象序列化一個(gè)xml聲明頭 encoding:xml的編碼 standalone:是否獨(dú)立
xs.startDocument("utf-8", true);
// 4.序列化一個(gè)根節(jié)點(diǎn) namespace:命名空間 name:標(biāo)簽的名稱
xs.startTag(null, "Smss");
// 5.循環(huán)遍歷list集合轻局,序列化一條條短信
for (SmsBean smsBean : lists) {
xs.startTag(null, "Sms");
//寫一個(gè)標(biāo)簽的屬性 namespace:命名空間 name:屬性的名稱 value :屬性的值
xs.attribute(null, "id", smsBean.id);
xs.startTag(null, "num");
xs.text(smsBean.num);//寫入一個(gè)標(biāo)簽的值
xs.endTag(null, "num");
xs.startTag(null, "msg");
xs.text(smsBean.msg);//寫入一個(gè)標(biāo)簽的值
xs.endTag(null, "msg");
xs.startTag(null, "date");
xs.text(smsBean.date);//寫入一個(gè)標(biāo)簽的值
xs.endTag(null, "date");
xs.endTag(null, "Sms");
}
// 6.序列化一個(gè)根節(jié)點(diǎn)的結(jié)束節(jié)點(diǎn)
xs.endTag(null, "Smss");
// 7.完成xml的寫入
xs.endDocument();
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
pull解析XML(反序列化)
//恢復(fù)短信
public static int restoreSms(Context context) {
ArrayList lists = null;
SmsBean smsBean = null;
try{
//1.創(chuàng)建一個(gè)XmlPullParser對(duì)象
XmlPullParser xpp = Xml.newPullParser();
//2.設(shè)置要解析的文件的流 in :讀取流 encoding:流的編碼
xpp.setInput(context.openFileInput("smsbackup2.xml"),"utf-8");
//3.獲取xml第一行的事件類型
int type = xpp.getEventType();
//4.循環(huán)判斷事件類型是否文檔結(jié)束
while (type!= XmlPullParser.END_DOCUMENT) {
String currentTagName = xpp.getName(); //獲取當(dāng)前標(biāo)簽的名稱
//5.不是文檔結(jié)束洪鸭,判斷是開始標(biāo)簽還是結(jié)束標(biāo)簽样刷,解析每一行的內(nèi)容以bean的方式封裝到list集合中,并且獲取下一行事件 的類型览爵。
switch (type) {
case XmlPullParser.START_TAG:
if("Smss".equals(currentTagName)){
//初始化一個(gè)list集合
lists = new ArrayList();
}else if("Sms".equals(currentTagName)){
//初始化一個(gè)SmsBean對(duì)象置鼻,并解析出id
smsBean = new SmsBean();
smsBean.id = xpp.getAttributeValue(null, "id");
}else if("num".equals(currentTagName)){
smsBean.num = xpp.nextText();//獲取內(nèi)容
}else if("msg".equals(currentTagName)){
smsBean.msg = xpp.nextText();//獲取內(nèi)容
}else if("date".equals(currentTagName)){
smsBean.date = xpp.nextText();//獲取內(nèi)容
}
break;
case XmlPullParser.END_TAG:
//當(dāng)前標(biāo)簽是結(jié)束標(biāo)簽并且是sms那么就將bean對(duì)象添加到list集合中
if ("Sms".equals(currentTagName)) {
lists.add(smsBean);
}
break;
default:
break;
}
//獲取下一行的事件類型
type = xpp.next();
}
//6.返回集合的size就是成功恢復(fù)的條數(shù)
return lists.size();
}catch (Exception e) {
e.printStackTrace();
}
return 0;
}