黑马android笔记

第二天 存储文件

TextUtils.isEmpty(var) 判断某个量var是否为空

“zhangtao”.equals(var)  判断var是否等于zhangtao

android:password="true" 表单设置成密码样式

private CheckBox check; check.isChecked()  选项被选中的判断

写文件:

FileOutputStream fos = new FileOutputStream(file);
fos.write(str.getBytes());

程序数据的根目录  /data/data/项目包名/

android studio 导入jar包  http://jingyan.baidu.com/article/e6c8503c7190b7e54f1a1893.html 要切换到project模式下操作,否则看不到libs包。删除包的话就是直接到项目目录下,找到libs包,删除即可。

Android Studio中调出DDMS的方法是按工具栏上的小绿色机器人,可以找到File Explorer

如果在程序中写 File file = new File("a.txt"); 这是要直接创建在应用程序的目录下,这是创建不成功的。应用程序的目录在 data/app/ 下,这个目录是不允许创建文件的。

每个应用都为其创建了一个文件 在/data/data/包名 下,这个才是其存放数据的文件夹。比如,File file = new File(""/data/data/com.example.zhangtao/info.txt""); 这样才是可以的。

context.getFilesDir(); // 帮助我们返回 data/data/包名/files 目录  例如: File file = new File(context.getFilesDir(),"context.txt");

context.getCacheDir(); 帮助我们返回 data/data/包名/cache 目录

利用context 直接写文件,可以不用context.getFilesDir(); 如下代码:(会自动保存在data/data/包名/files 目录下)

FileOutputStream fos = context.openFileOutput("private.txt",Context.MODE_PRIVATE);

fos.write("aabb".getBytes());
fos.close();

别的应用读取另外一个应用的文件,文件路径必须写死了。不可采用context的api,否则会读取到本应用的路径

MODE_PRIVATE         这是默认的形式,配置文件只允许本程序和享有本程序ID的程序的访问   0

MODE_WORLD_READABLE   允许其他的应用程序读文件                                                                   1

MODE_WORLD_WRITEABLE   允许其他的应用程序写文件                                                                 2   这俩好像过期了,不知用何取代

MODE_MULTI_PROCESS       主要用于多任务,2.3版本当多个进程共同访问的时候,必须指定这个标签

 

 一个错误,待究:

如果在方法外定义 Context context; 然后方法内调用 context.openFileOutput() 则报错

把Context context作为参数则没有问题。

文件的权限:私有文件 别的应用既不可读也不可写。可读文件 别的应用只可读 不可写 。 可写文件 别的应用只可写,不可读。可读可写文件,别的应用既可读又可写,也即创建文件时,权限部分的格式是:Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE 

存储文件到SD卡,必须在manifest.xml文件中添加uses permission权限android.permission.WRITE_EXTERNAL_STORAGE 权限。

在4.0以前版本,读sd卡是不需要权限的。在4.0以后版本,考虑到这个问题:在  开发者选项 -- 对SD卡进行读写保护   有这个选项,勾选之后,读取sd卡数据也需要权限了。此时,必须加上android.permission.READ_EXTERNAL_STORAGE  权限之后 ,才可以读

即在manifest.xml文件中添加:<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE "> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE ">

Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()  SD卡是否挂载的判断

File file = new File(Environment.getExternalStorageDirectory(),"sd.txt"); 在SD卡目录创建文件的代码

// 在DDMS(Android Device Monitor)中 文件是保存在 /storage/sdcard/ 目录下的

另外,其实 Enviroment.getDataDirectory() 其实就是得到手机data的目录 类同用Context API 得到的目录,可相互比较一下

SharedPreferences存储

public void writeSP(View view){
SharedPreferences sp = getSharedPreferences("config",Context.MODE_PRIVATE);   ---  将生成 data/data/包名/shared_prefs/config.xml 文件  注意,此时不会生成,只是在最后commit之后才会创建
SharedPreferences.Editor editor = sp.edit();   -- 获取编辑器

editor.putString("username","zhangtao");  -- 存储
editor.putInt("age",36); -- 存储

editor.commit();  -- 类似事务,提交
}


public void readSP(View view){
SharedPreferences sp = getSharedPreferences("config",Context.MODE_PRIVATE);   -- 获取 config.xml文件

String username = sp.getString("username","");   -- 第二项是若是取不到的默认值
Integer age = sp.getInt("age",0);

Toast.makeText(this,username+age,Toast.LENGTH_SHORT).show();
}

android 生成xml文件

第一种方式:

StringBuffer sb = new StringBuffer();

sb.append("<?xml version="1.0"  encoding="utf-8" ");

sb.append().......

.................

然后再按照通常的方法创建输出流写入即可。

fos.write(sb.toString().getBytes());

第二种方式是用XmlSerializer 方式,待研

 常说序列化,何为序列化,也即信息从内存写到文件里去。

/*
* 利用XML序列化的方法 XmlSerializer serializer = Xml.newSerializer(); 生成XML文件
* */
public void createXML(View view){

 try {

File file = new File(Environment.getExternalStorageDirectory(),"sms.xml");
FileOutputStream fos = new FileOutputStream(file);

XmlSerializer serializer = Xml.newSerializer(); // 创建xml序列化器
serializer.setOutput(fos,"utf-8");

serializer.startDocument("utf-8",true);
serializer.startTag(null,"province"); // null 指的是命名空间为空
serializer.attribute(null,"id","shandong");

serializer.startTag(null,"city");
serializer.text("rizhao");
serializer.endTag(null,"city");

serializer.startTag(null,"zipcode");
serializer.text("0633");
serializer.endTag(null,"zipcode");

serializer.startTag(null,"city");
serializer.text("jinan");
serializer.endTag(null,"city");

serializer.startTag(null,"zipcode");
serializer.text("0531");
serializer.endTag(null,"zipcode");

serializer.endTag(null, "province");
serializer.endDocument();

} catch (Exception e) {
e.printStackTrace();
} finally {
Toast.makeText(this,"you have do it sucessfully!",Toast.LENGTH_SHORT).show();
}

}


public void readXML(View view){

List<String> cities = null;

try {
File file = new File(Environment.getExternalStorageDirectory(),"sms.xml");
FileInputStream fis = new FileInputStream(file);

XmlPullParser parser = Xml.newPullParser(); // 创建pull解析器
parser.setInput(fis,"utf-8");

int type = parser.getEventType();  

while (type != XmlPullParser.END_DOCUMENT){

switch (type){

case XmlPullParser.START_TAG:

if ("province".equals(parser.getName())) { // 解析到全局开始的标签
cities = new ArrayList<String>(); // 初始化list
} else if ("city".equals(parser.getName())){
cities.add(" city: "+parser.nextText());
} else if ("zipcode".equals(parser.getName())){
cities.add(" zipcode: "+parser.nextText());
}

break;

case XmlPullParser.END_TAG:
if ("province".equals(parser.getName())){
Toast.makeText(this,cities.toString(),Toast.LENGTH_LONG).show();
   }

type = parser.next();  }

} catch (Exception e) {
e.printStackTrace(); }
}

 关于xml解析的内容,详情可查看 http://blog.csdn.net/andyhuabing/article/details/8036340

第三天 数据库及内容提供者 (ContentProvider)

1、自定义SQLiteOpenHelper,需注意;必须实现 onCreate 和 onUpgrade 方法 以及 构造方法。构造方法中有Context参数,必须在方法外 自定义helper类内部,定义一个属性 private Context myContext ,然后在构造方法中,赋值Context属性  myContext = context; 否则会出错! 

Android Studio中插入代码的快速方法是 Alt + Insert 键

定义数据库 SQLiteDatabase db ,执行sql语句的语法是 db.execSQL(sql) ,sql语句的写法与mysql中基本相同、

创建数据库的流程就是,利用自定义的SQLiteHelper 来进行,如下:

MySQLiteOpenHelper myHelper = new MySQLiteOpenHelper(this,"zhangtao.db",null,1);  zhangtao.db 数据库  1为数据库版本
myHelper.getWritableDatabase();   //  这个过程应该会? 创建数据库zhangtao.db ,同时,会执行自定义helper中覆写的onCreate()方法,若此方法中定义的执行的创建表的语句,则表会创建( db.execSQL(sql) 方法)
该方法的返回值是一个SQLiteDatabase ,即要进行数据库增删改查,应该首先获取数据库。

如果此时想再在zhangtao.db中创建另外一个表,可以首先在自定义的helper中,覆写onUpgrade方法,将建表语句写进去,然后
MySQLiteOpenHelper myHelper = new MySQLiteOpenHelper(this,"zhangtao.db",null,2);   myHelper.getWritableDatabase(); 
这样,因为数据库版本更新了,再次调用 myHelper.getWritableDatabase();的时候,会执行onUpgrade方法,就会把预先定义在其中的 新增加表的语句执行。 

 SQLiteDatabase数据库的增删改查

首先获取数据库 

myHelper = new MySQLiteOpenHelper(this,"zhangtao.db",null,2);
SQLiteDatabase db = myHelper.getWritableDatabase();

利用ContentValues来添加值,此类支持键值对的存储。如下示例

增:
values.put("name","liudehua");
values.put("age",54);
values.put("intro","pop star");

db.insert("people",null,values); // 必须在此插入people表,否则后面values清空了 或者 是值被替代了
values.clear();

values.put("name","guofucheng");
values.put("age",50);
values.put("intro","model and pop star");

long result = db.insert("people",null,values); // 操作失败的话 会返回 -1

删:int result = db.delete("people","id = ?",new String[]{"4"}); 操作失败也是返回 -1
改:int result = db.update("people",values,"id = ?",new String[]{"3"}); 需要首先构建要更新的ContentValues值
查:
Cursor cursor = db.rawQuery("select * from people where id > ?",new String[]{"1"});

if(cursor.moveToFirst()){
do {
String name = cursor.getString(cursor.getColumnIndex("name"));
String age = cursor.getString(cursor.getColumnIndex("age"));
String intro = cursor.getString(cursor.getColumnIndex("intro"));

Log.d("query result","name is: "+name+" age is: "+age+" intro is: "+intro);

} while (cursor.moveToNext());
}

需要构建Cursor 以及利用原生sql查询的rawQuery方法 ,循环取值的 cursor.moveToFirst() cursor.moveToNext() cursor.getString(cursor.getColumnIndex("name")) 等

第六天 广播

1、自定义广播的方式

首先

Intent intent = new Intent();

intent.setAction("com.mavict.customBroadcast"); // 自定义的action,要定义在广播中

sendBroadcast(intent);

然后,自定义接受者com.example.day6.MyReceiver,继承BroadcastReceiver,覆写如下方法,处理获得广播之后的行为。

@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
Toast.makeText(context,"获得到了自定义的广播事件", Toast.LENGTH_SHORT).show();
}

在manifest.xml文件中定义自定义的Receiver
<receiver android:name="com.example.day6.MyReceiver" >
<intent-filter>
<action android:name="com.mavict.customBroadcast" />
</intent-filter>
</receiver>
注意 intent-filter 中的action

第九天 Fragment等

1、特点

fragment是轻量级的activity, 不需要在清单文件中配置。可以在一个Activity中同时出现多个Fragment,并且一个Fragment也可以在多个Activity中使用;
在Activity运行过程中,可以添加、移除或者替换Fragment;
Fragment可以响应自己的输入事件,并且有自己的生命周期,它们的生命周期会受宿主Activity的生命周期影响。

2、静态创建两个fragment

A 步骤 在显示布局main_activity.xml文件中定义fragment标签 fragment1  fragment2     --------        <fragment  ..... /> 

B 继承Fragment,创建两个类 Fragment1  Fragment2  。注意名称要和上面xml中标签的名字一致。同时另外创建两个xml布局文件(设为f1.xml  f2.xml),以为这两个Fragment类创建布局视图

C  类 Fragment1  Fragment2 中,覆写 onCreateView 方法,同时返回 return  inflater.inflate(R.layout.f1,null )  ;  return  inflater.inflate(R.layout.f2,null ) ; 即为两个fragment创建了视图

到此OK 

3、动态创建fragment

A、可以不在main_activity.xml文件中定义任何fragment标签,而只在Activity类中动态的添加或删除fragment

B、Activity中的代码如下

//1.判断当前手机的朝向
int width = getWindowManager().getDefaultDisplay().getWidth();
int height = getWindowManager().getDefaultDisplay().getHeight();

Fragment1 fragment1 = new Fragment1();  
Fragment2 fragment2 = new Fragment2();

FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();


if(width>height){    

 ft.replace(android.R.id.content, fragment1);   //水平方向    android.R.id.content指的是当前Activity所在的那个视图。也可为xml文件中的LinearLayout等设置id,然后调用这些id,则会在相应视图中加fragment  

}else{    ft.replace(android.R.id.content, fragment2);    }

ft.commit();
}

4、利用Fragment创建选项卡

通常选项卡是用ViewPager实现的。但是用Fragment也是可以实现的。也即点击不同的标签,加载不同的fragment即可。例如下代码

public void onClick(View v) {
ft = fm.beginTransaction();
switch (v.getId()) {
  case R.id.tab1: ft.replace(R.id.content, new Fragment1());
  break;

  case R.id.tab2:
        ft.replace(R.id.content, new Fragment2());
        break;

  case R.id.tab3:
  ft.replace(R.id.content, new Fragment3());
  break;
  

  case R.id.tab4:
  ft.replace(R.id.content, new Fragment4());break;

  }
ft.commit();
}

R.id.content 是main_activity.xml中的一块显示内容区域的LinearLayout的id

5、两个Fragment之间的通讯。比如点击 Fragment1中的按钮,修改Fragment2中的文本

在类Fragment1中的onCreateView覆写方法中,添加如下代码

View view = inflater.inflate(R.layout.fragment1, null);  // 得到fragment1的视图View
Button button = (Button) view.findViewById(R.id.bt);  // 通过上面得到的fragment1的视图view,找到fragment1上面的按钮
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
System.out.println("在fragment里面相应了点击事件");
Fragment2 f2 = (Fragment2) getActivity().getFragmentManager().findFragmentById(R.id.fragment2);  

// getActivity(). 是指当前得到当前fragment1所绑定的activity(fragment2也绑定在内),再通过Activity的方法getFragmentManager().得到Fragment的Manager,再去通过findFragmentById得到fragment2(当然fragment2的id要事先在main_activity.xml中有定义)  这样就得到了Fragment2 

f2.setText("内容变化了...");  // 通过调用Fragment2中内部定义的方法,来修改其内的文本
}
});

添加关于ViewPager的内容

第一步,在xml布局文件中(例如 guide.xml),定义ViewPager的标签,如下:

<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

第二步,创建 ViewPager的自定义数据适配器MyPageAdapter,通过继承PageAdapter类,并覆写如下方法实现:

private List<View> views;      // 用来盛放 多个页卡的View

public MyPagerAdapter(List<View> views) {
this.views = views;
}

// 实例化(初始化)页卡
@Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(views.get(position));
return views.get(position);
}

// 销毁页卡
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(views.get(position));
//super.destroyItem(container, position, object);
}

@Override
public int getCount() {
if (views != null){ return views.size(); }
return 0;
}

@Override
public boolean isViewFromObject(View view, Object object) {
return (view == object); // 官方提示这样写
}

第三步,Guide.java类中(implements ViewPager.OnPageChangeListener ),做如下设置,实现选项卡

private ViewPager viewPager;    
private MyPagerAdapter myPagerAdapter;
private List<View> views; // 页卡视图List
private View view1,view2,view3; // 要装载的页卡视图

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.guide);

initView(); // 初始化视图
initData(); // 初始化数据
}
// 初始化视图
private void initView(){

// 将轮播视图装载入views
LayoutInflater inflater = LayoutInflater.from(this);
view1 = inflater.inflate(R.layout.guide1,null);
view2 = inflater.inflate(R.layout.guide2,null);
view3 = inflater.inflate(R.layout.guide3,null);
//view4 = inflater.inflate(R.layout.guide4,null);

views = new ArrayList<View>();
views.add(view1);
views.add(view2);
views.add(view3);
//views.add(view4);

// 实例化adapter
viewPagerAdapter = new ViewPagerAdapter(views);
// 获取viewPager
viewPager = (ViewPager) findViewById(R.id.viewpager);

}

// 初始化数据
private void initData(){
// 设置adapter进viewPager
viewPager.setAdapter(viewPagerAdapter);
// 设置 viewPager的监听
viewPager.setOnPageChangeListener(this);
}

完工 OK
原文地址:https://www.cnblogs.com/appzhang/p/4374298.html