• 中级实训Android学习记录——RecyclerView、Android存储


    学习记录 2020/11/26

    RecyclerView

    • RecyclerView

    RecyclerView在之前就学习过,但用的时候才发现没有学习记录,所以在这里自行总结。

    使用RecyclerView建立列表视图的步骤:

    1. 创建一个activity(Android studio会帮你顺便声明并创建layout),在activity的xml文件中建立一个RecyclerView

      // 我们在activity_linear_recycler.xml中声明一个RecyclerView
          <androidx.recyclerview.widget.RecyclerView
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              app:layout_constraintStart_toStartOf="parent"
              app:layout_constraintTop_toTopOf="parent"
              android:id="@+id/rv_main"
              android:background="@color/purple_700"/>
      
    2. 建立一个列表的一个小项所用的layout

      // 这里我们建立的是layout_linear_item.xml,里面只有一个简单的TextView
          <TextView
              android:id="@+id/tv_title"
              android:layout_width="match_parent"
              android:layout_height="50dp"
              android:textColor="#000"
              android:textSize="20sp"
              app:layout_constraintBottom_toBottomOf="parent"
              app:layout_constraintEnd_toEndOf="parent"
              app:layout_constraintStart_toStartOf="parent"
              app:layout_constraintTop_toTopOf="parent" />
      
    3. 建立使用小项layout的RecyclerViewAdapter

      public class LinearAdapter extends RecyclerView.Adapter<LinearAdapter.LinearViewHolder> {
      // 自己创建一个ViewHolder并将它传入Adapter的模板参数中
          private Context mContext;
      
          public  LinearAdapter(Context context) {
              this.mContext = context;
          }
      
          
          // 注意这里的返回值也要改成自己的ViewHolder
          @NonNull
          @Override
          public LinearAdapter.LinearViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
              return new LinearViewHolder(LayoutInflater.from(mContext).inflate(R.layout.layout_linear_item, parent, false));
          }
      
          // 注意这里传入的参数也要改成自己的ViewHolder
          @Override
          public void onBindViewHolder(@NonNull LinearAdapter.LinearViewHolder holder, int position) {
              holder.textView.setText("Hello World!");
          }
      
          // 自定义一个列表的小项的个数,一般我们可以使用一个列表来声明
          @Override
          public int getItemCount() {
              return 30;
          }
      
          // 建立一个ViewHolder来自定义小项
          class LinearViewHolder extends  RecyclerView.ViewHolder {
      
              private TextView textView;
      
              public LinearViewHolder(@NonNull View itemView) {
                  super(itemView);
                  textView = itemView.findViewById(R.id.tv_title);
              }
          }
      
      }
      
    4. 最后就可以在Activity中直接使用RecyclerView

    // 先声明一个变量 private RecyclerView mRvMain;
            mRvMain = findViewById(R.id.rv_main);
            mRvMain.setLayoutManager(new LinearLayoutManager(LinearRecyclerActivity.this));
           
            mRvMain.setAdapter(new LinearAdapter(LinearRecyclerActivity.this));
    
    1. 加每个小项之间的分隔线的方法

      1. 在Activity.java中自定义一个类并继承ItemDecoration

        class myDecoration extends RecyclerView.ItemDecoration {
                @Override
                public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
                    super.getItemOffsets(outRect, view, parent, state);
                    outRect.set(0, 0, 0, getResources().getDimensionPixelOffset(R.dimen.dividerHeight));
                }
            }
        // 这里的set函数的四个参数代表的方向依次是左、上、右、下
        // 所以我们的效果其实是在每个item的下方加一个R.dimen.dividerHeight大小的横线
        
      2. 调用RecyclerView的addItemDecoration方法即可

      mRvMain.addItemDecoration(new myDecoration());
      

    Android 存储

    • SharedPreferences 轻量级数据存储

      • 一般存储形式表现为以Key-Value的形式,存储在XML文件中
      • 用SharedPreferences来读取xml文件
      • 用SharedPreferences.Editor来更改xml文件
    • SharedPreferences 用法

      • 获取数据

      • private SharedPreferences mSharedPreferences;
        mSharedPreferences = getSharedPreferences("data", MODE_PRIVATE); // 这里第一个参数表示文件名,第二个参数表示文件打开的模式,一般使用MODE_PRIVATE
        
        // 假设已经使用Editor输入数据,key="name"
        
        String data = mSharedPreferences.getString("name", "");
        
      • 输入数据

      • private SharedPreferences.Editor mEditor;
        mEditor = mSharedPreferences.edit();
        //调用put类型的方法来输入key-value数据
        mEditor.putString("name", "haha")
        // 调用apply或者commit进行数据更新
         // apply是异步
         // commit是同步
        mEditor.apply(); 
        
      • SharedPreferences的存储目录

        • /data/data//shared_prefs
      • SharedPreferences的存储目录的查看方式

      • 命令行下

      • // 使用android的shell
        adb shell
        // 调用run-as 后面加上自己的完整applicaiton的名称
        run-as com.skypan.helloworld
        // 进入目录shared_prefs
        cd shared_prefs
        // 在命令行中列出data.xml的内容
        cat data.xml
        
    • 存储概念

      • Android存储分为
        • 内部存储(Internal Storage)
          • 内部存储会随应用的卸载而删除,如
            • /data/data//shared_prefs
            • /data/data//databases
            • /data/data//files
            • /data/data//cache
          • 利用的方法可以是
            • context.getFilesDir()获得目录/data/data//files
            • context.getCacheDir()获得目录/data/data//cache
        • 外部存储(External Storage)
          • 公有目录
            • 公有目录的获取
              • Environment.getExternalStoragePublicDirectory(int type)
              • type可以是Environment下的已经定义好的变量
          • 私有目录,随应用的卸载而删除,如
            • /mnt/sdcard/Anroid/data/data//cache
            • /mnt/sdcard/Anroid/data/data//files
    • File内部存储

      • 使用的类

      • FileOutputStream,FileInputStream

      • 存储数据

        private void save(String content) {
        	try {
             FileOutputStream fileOutputStream = openFileOutput("test.txt", MODE_PRIVATE); // 第一个参数代表文件名,第二个参数是文件读写方式
             fileOutputStream.write(content.getBytes());
             // 这里调用的write函数接受的是byte[],所以需要将String对象转换成byte
         } catch (IOException e) {
             // 注意,此时其实丢出的不止是IOException,还有FileNotFoundException,不过这个错误继承了IOException,所以都可以被IOException catch到
             e.printStackTrace();
         } finally { // 无论如何,我们都需要关闭一开始打开的文件
             if (fileOutputStream != null) { 
                 // 如果已经打开了,就关闭
                 try {
                     fileOutputStream.close();
                 } catch (IOException e) {
                     e.printStackTrace();
                 }
             }
         }
        }
        

        读取数据

        private String read() {
         FileInputStream fileInputStream = null;
         try {
             FileInputStream fileInputStream = openFileInput("test.txt");
             byte[] buff = new byte[1024];
             StringBuilder sb = new StringBuilder("");
             int len = 0;
             while((len = fileInputStream.read(buff)) > 0) {
                 sb.append(new String(buff, 0, len));
                 // 从buff的0开始,将len长度的byte做成String加到sb的后面
             }
             return sb.toString();
         } catch (IOException e) {
             e.printStackTrace();
         
             // 默认可能发生错误,直接返回空
             return null;
        }
        
    • File外部存储

      • 使用的类

      • FileOutputStream,FileInputStream,Environment

      • 存储数据

        private void save(String content) {
        	try {
             File dir = new File(Environment.getExternalStorageDirectory(), "skypan");
        // 第一个是找到外部存储目录,第二个参数是文件夹的名字
             if (!dir.exists()) {
                 dir.mkdirs();
                 // 使用mkdirs而非mkdir是因为他会帮我们创建一系列的文件夹(当我们的文件夹路径很复杂的时候)
             }
             File file = new File(dir, "test.txt");
             if (!file.exists()) {
                 file.createNewFile();
             }
             FileOutputStream fileOutputStream = new FileOutputStream(file);
             
             fileOutputStream.write(content.getBytes());
             // 这里调用的write函数接受的是byte[],所以需要将String对象转换成byte
         } catch (IOException e) {
             // 注意,此时其实丢出的不止是IOException,还有FileNotFoundException,不过这个错误继承了IOException,所以都可以被IOException catch到
             e.printStackTrace();
         } finally { // 无论如何,我们都需要关闭一开始打开的文件
             if (fileOutputStream != null) { 
                 // 如果已经打开了,就关闭
                 try {
                     fileOutputStream.close();
                 } catch (IOException e) {
                     e.printStackTrace();
                 }
             }
         }
        }
        

        读取数据

        private String read() {
         FileInputStream fileInputStream = null;
         try {
             File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+File.separator+"skypan", "test.txt");
             // 第一个参数是我们的文件夹的绝对路径,其中File.separator的值="/",第二个参数是我们的文件名
             fileInputStream = new FileInputStream(file);
             byte[] buff = new byte[1024];
             StringBuilder sb = new StringBuilder("");
             int len = 0;
             while((len = fileInputStream.read(buff)) > 0) {
                 sb.append(new String(buff, 0, len));
                 // 从buff的0开始,将len长度的byte做成String加到sb的后面
             }
             return sb.toString();
         } catch (IOException e) {
             e.printStackTrace();
         
             // 默认可能发生错误,直接返回空
             return null;
        }
        

        注意,并不能直接使用以上代码,在使用外部存储之前,我们需要先获取外部存储的读写权限

        1. 在AndroidManifest.xml中声明以下语句

          <user-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
          
        2. 如果在build.gradle中,我们的sdk版本超过了23,我们还需要动态申请权限

          在build.gradle中查看sdk版本

          compileSdkVersion n
          

          如果$ngeq 23$,就需要动态申请权限,在使用外部存储之前:

          ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WIRTE_EXTERNAL_STORAGE}, 1);
          // 第一个参数是调用这个函数的activity(context),第二个参数是申请的是什么权限,第三个是权限返回结果的识别码,如果我们需要得到用户是否确认给予权限,我们需要额外调用方法进行判断
          

        在申请了权限之后,就可以正常的运行之前说的使用外部存储的代码了。

  • 相关阅读:
    2013-05-25 14:04 zend studio10正式版如何汉化?
    网页前端优化之滚动延时加载图片
    appium框架之bootstrap
    软件测试面试题(一)
    Java中的经典算法之冒泡排序(Bubble Sort)
    Git知识总览(一) 从 git clone 和 git status 谈起
    Webdriver获取多个元素
    idea注册码到期,破解idea
    安装appium桌面版和命令行版
    Python+Appium学习篇之WebView处理
  • 原文地址:https://www.cnblogs.com/lwfing/p/14053985.html
Copyright © 2020-2023  润新知