Android 手机存储与RecycleView显示

本文介绍了Android手机的内部和外部存储,包括它们的区分、获取路径以及权限管理。特别讨论了RecycleView在显示数据时的排序方法,并给出了相关代码示例。
摘要由CSDN通过智能技术生成

Android 手机存储与RecycleView显示


参考 博客 https://blog.csdn.net/ezconn/article/details/103285670

1. android手机存储分类

分为:内部存储和外部存储

如何区分内部存储和外部存储:可以从物理和逻辑区分

从物理的角度区分,内部存储就是手机自带存储空间,外部存储就是外部接入的存储空间例如SD卡

从逻辑意义上区分,data,system 目录就是手机的内部存储,而 mnt 或者 storage目录下的sdcard0指向的sdcard目录就是外部存储。如果是手机自带的外部存储被称为机身外部存储,外置的SD卡则称之为外部存储。当然两者都称为外部存储也没关系。这里描述的内部存储和机身外部存储都属于机身存储;

2. 内部存储

获取内部存储路径和api对应关系

1,通过Environment

Environment.getDataDirectory()                /data

Environment.getRootDirectory()                /system

Environment.getDownloadCacheDirectory()            /data/cache

2,通过上下文Context

getCacheDir()                /data/user/0/包名/cache

getFilesDir()                /data/user/0/包名/files

Build.VERSION_CODES.LOLLIPOP及以上版本新增的API

getDir("靓仔", MODE_PRIVATE)           /data/user/0/包名/app_靓仔

getNoBackupFilesDir()                 /data/user/0/包名/no_backup

getCodeCacheDir()                     /data/user/0/包名/code_cache

Build.VERSION_CODES.N及以上版本新增的API

getDataDir()                  /data/user/0/包名

特点:

1、内部存储路径中的文件是分类存储的,我们无法干涉,除了cache目录,别的目录系统不会自动创建

2、除了files目录,别的目录我们几乎都是无法手动操作的

3、别的App几乎无法访问内部存储中的数据,除了用非法手段或者我们主动暴露

4、内部存储目录下的文件夹及文件会随着app的卸载而被系统自动删除

3. 外部存储

外部存储又可分为共有目录和私有目录;

私有目录 私有目录:不需要访问权限

Android 在外部存储空间中也提供了特殊目录供App存放私有文件,该路径为:

/storage/emulated/0/Android/data/包名/

注意:应用安装之后/storage/emulated/0/Android/data/是没有对应的应用文件夹的,需要手动调用对应的API创建;

获取私有目录路径

getObbDir()                           /storage/emulated/0/Android/obb/包名 

getExternalCacheDir()          /storage/emulated/0/Android/data/包名/cache

getExternalFilesDir(null)       /storage/emulated/0/Android/data/包名/files

公有目录 公有目录:需要申请权限才能访问

权限:6.0以上需要动态申请

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

获取共有目录的API 29中已过时:

Api	路径
Environment.getExternalStorageDirectory() 	 /storage/emulated/0
Environment.getExternalStoragePublicDirector(Environment.DIRECTORY_DOWNLOADS)

获取共有目录,例如Download共有目录

/storage/emulated/0/Download
官方的解释:

在API级别29中不赞成使用此方法。为了提高用户隐私,不建议直接访问共享/外部存储设备。当应用定位到时 Build.VERSION_CODES.Q,此方法返回的路径不再可供应用直接访问。应用程序可以继续访问内容通过迁移到替代品,如存储在共享/外部存储 Context#getExternalFilesDir(String)MediaStoreIntent#ACTION_OPEN_DOCUMENT。

注意:如果手机插入SD卡,可通过getExternalFilesDirs或getExternalCacheDirs遍历来获取路径;

4. 数据删除

CLEAR DATA(删除数据): 清除的是 data/data/对应程序包名 的文件夹下的所有的文件全都会被删除,mnt/sdcard/Android/对应程序包名 下的所有的数据也都会被删除。

CLEAR CACHE(清空缓存): 清除的数据是 data/data/对应程序包名/catch 目录下的数据,还有 mnt/sdcard/Android/对应程序包名/catch目录下的数据

5. 权限相关

在android
6.0以前,你可以只关注外置存储是否挂载即可,但是从6.0以后,也就是M系统后,还需要判断是否有读写权限,只有具备这些权限才可以读写外置存储。

1,Context.getRootDirectory

获取路径:/system
默认存在,不可读写(除非具备root权限)

2,Environment.getDownloadCacheDirectory

获取路径:/cache
默认存在,声明权限则可读写(6.0和以后系统还需要向用户申请同意才可以)

3,Context.getFilesDir

获取路径:/data/user/0/包名/files
该目录是应用的文件存储目录,应用被卸载时,该目录一同被系统删除。默认存在,默认具备读写权限(6.0系统可以不用向用户申请)

4,Context.getCacheDir

获取路径:/data/user/0/包名/cache
该目录是应用的文件缓存目录,应用被卸载时,该目录一同被系统删除。默认存在,默认具备读写权限。不同于getFileDir,该目录下的文件在系统内存紧张时,会被清空文件,来腾出空间供系统使用,著名的图片加载库ImageLoader就是在没有外置存储读写权限时使用此文件夹。getFileDir,不会因为系统内存不足而被清空。(6.0系统可以不用向用户申请)

5,Context.getDir

获取路径:/data/user/0/应用包名/app_参数名
默认存在,可读写。分为Private等三个权限,private代表仅能自己访问。(6.0系统可以不用向用户申请)

6,Context.getCodeCacheDir

获取路径:/data/user/0/包名/code_cache
默认存在,可读写。(6.0系统可以不用向用户申请)

7,getNoBackupFilesDir()

获取路径: /data/user/0/包名/no_backup
默认存在,可读写。(6.0系统可以不用向用户申请)

8,Context.getObbDir

获取路径:/storage/emulated/0/Android/obb/包名
该目录是应用的数据存放目录,一般被用来存放游戏数据包obb文件。默认存在,可读写(6.0系统可以不用向用户申请)

9,Context.getExternalCacheDir

获取路径:/storage/emulated/0/Android/data/应用包名/cache
默认存在,可读写。(6.0系统可以不用向用户申请)

10,Context.getExternalFilesDir

获取路径:(以下载目录为准) /storage/emulated/0/Android/data/应用包名/files/Download
默认存在,可读写。(6.0系统可以不用向用户申请)

11,Environment.getExternalStorageDirectory

获取路径:/storage/emulated/0
默认存在,声明权限则可读写(6.0和以后系统还需要向用户申请同意才可以)

12,Environment.getExternalStoragePublicDirectory

获取路径:/storage/emulated/0/Download(以下载目录为例)
默认存在,声明权限则可读写(6.0和以后系统还需要向用户申请同意才可以)

13,Context.getDatabasePath

获取路径:/data/user/0/包名/databases/参数名
默认不存在,可读写。(6.0系统可以不用向用户申请)

14,Context.getPackageCodePath

获取路径:/data/app/包名-1/base.apk
默认存在,获取apk包路径

15,Context.getFileStreamPath

获取路径:/data/data/包名/files/download(示例download
该目录是应用的文件存储目录,应用被卸载时,该目录一同被系统删除。默认存在,默认具备读写权限(6.0系统可以不用向用户申请)

附注:

a)上述路径是通过getAbsulotePath方法获得,一般情况下等同于getPath
b)在6.0系统上,一般Java层实现对外置存储的文件操作需要向用户申请,如果用C层实现,则可以越过这种限制
c)配置compilesdk,targetsdk低于23,可以避免在6.0手机上的权限限制

6. 代码展示

  • 实现按照文件名排列
  • 使用RecycleView
  • 使用Collections.sort方法
  • 添加权限:<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
package cn.study.project.study_view_improve;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private MyAdapter adapter;



    @SuppressLint("ClickableViewAccessibility")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        RecyclerView recyclerView=findViewById(R.id.recyclerview);
        List<File>  list = getFileList();

        adapter = new MyAdapter(MainActivity.this,list);
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
    }

    public void onClickButtonByType(View view){
        List<File> list = getFileList();
        adapter.setmList(list);
    }

    public void onClickButtonByName(View view){
        List<File> list = getFileList();
        Collections.sort(list, new Comparator<File>() {
            @Override
            public int compare(File o1, File o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });
        adapter.setmList(list);
    }

    public List<File> getFileList(){
        List<File> list=new ArrayList<>();
        File path= this.getCacheDir();
        Log.d("debug_path","ExternalStorageDirectory--"+path.getAbsolutePath());
        File[] files=path.listFiles();
        if(files!=null){
            for (File file : files) {
                if (file.isFile())
                    list.add(file);
            }
        }
        Log.d("debug_list_size", String.valueOf(list.size()));
        return list;
    }
}
  • 自定义 RecycleView.Adapter
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {

    private List<File> mList;
    private Context mContext;

    public void setmList(List<File> mList) {
        this.mList = mList;

    }

    public MyAdapter(Context mContext, List<File> mList) {
        this.mList = mList;
        this.mContext = mContext;
    }

    @NonNull
    @Override
    public MyAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view= LayoutInflater.from(mContext).inflate(R.layout.view_holder_layout,parent,false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull MyAdapter.ViewHolder holder, int position) {
        File item = mList.get(position);
        holder.view.setText(item.getName());
    }

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

    static class ViewHolder extends RecyclerView.ViewHolder{

        private TextView view;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            view = itemView.findViewById(R.id.tv_show);
        }
    }
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值