zoukankan      html  css  js  c++  java
  • 黑马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
  • 相关阅读:
    java--io流之转换流
    java--IO流之字节流、字符流
    java--递归
    java--IO流之File类
    java --JDBC
    2018-09-15JDBC事务详解1
    2018-09-10JSP内容和标签的查看权限+9个内置对象
    2018-09-12DBUtils工具包+DBCP连接池
    2018-09-08Cookie的发送和Cookie的读取+Session基本原理
    参考博客:URI和URL的区别
  • 原文地址:https://www.cnblogs.com/appzhang/p/4374298.html
Copyright © 2011-2022 走看看