目录

第一节:RecyclerView列表流行控件

一、RecyclerView是什么

二、RecyclerView的优点

三、编写一个简单的RecyclerView

1、导入RecyclerView依赖包

2、添加RecyclerView控件

3、创建item的布局文件item_layout.xml

4、创建适配器,这里使用了Gilde需要导包。

5、为RecyclerView设置LayoutManager

6、创建适配器实例,并设置给RecyclerView

7、为RecyclerView添加点击事件。

8、切换布局,三种布局循环切换。

9、插入、删除item,并设置动画:

第二节:NDK入门

一、NDK简介

二、优缺点及使用场景

三、NDK的配置

Mac/Linux配置

Windows配置

Android Studio的配置

第三节:实战:有声阅读器

第四节:扩展学习--GIF介绍


第一节:RecyclerView列表流行控件

一、RecyclerView是什么

RecyclerView是support-v7包中的新组件,与经典的ListView相比,同样拥有item回收复用的功能。

二、RecyclerView的优点

RecyclerView是ListView的升级版,有如下优点:

(一)RecyclerView封装了ViewHolder的回收复用

(二)提供了一种插拔式的体验,高度的解耦,异常的灵活,内置了三种LayoutManager:

  • LinearLayoutManager--横向或纵向滑动的列表
  • GridLayoutManager--类似于GridView的效果
  • StaggeredGridLayoutManager--可以实现瀑布流的效果

(三)可以控制Item增删的动画,并支持自定义动画

三、编写一个简单的RecyclerView

1、导入RecyclerView依赖包

在build.gradle中添加

implementation 'com.android.support:appcompat-v7:28.+'implementation 'com.android.support:recyclerview-v7:28.+'//注意recyclerview的版本号必须与appcompat版本号一致

*补充内容,如果Androidx则只需要导包:

implementation 'com.google.android.material:material:1.0.0'

2、添加RecyclerView控件

        

3、创建item的布局文件item_layout.xml

<?xml version="1.0" encoding="utf-8"?>        

4、创建适配器,这里使用了Gilde需要导包。

implementation "com.github.bumptech.glide:glide:4.9.0"
public class MyRecyclerViewAdapter extends RecyclerView.Adapter {    private Context mContext;    private List mLists;    public MyRecyclerViewAdapter(Context mContext) {        this.mContext = mContext;        this.mLists = new ArrayList<>();    }    public void setDataSource(List dataSource) {        mLists = dataSource;        notifyDataSetChanged();    }    @NonNull    @Override    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {        View view = LayoutInflater.from(mContext).inflate(R.layout.item_layout, parent, false);        return new ViewHolder(view);    }    @Override    public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {        //绑定数据        holder.mTitle.setText(mLists.get(position));        Glide.with(mContext).load(getIcon(position)).into(holder.mIcon);    }    @Override    public int getItemCount() {        return mLists.size();    }    private int getIcon(int position) {        switch (position % 5) {            case 0:                return R.drawable.a;            case 1:                return R.drawable.b;            case 2:                return R.drawable.c;            case 3:                return R.drawable.d;            case 4:                return R.drawable.e;            default:                return R.drawable.tree;        }    }    class ViewHolder extends RecyclerView.ViewHolder {        public View mItemView;        public ImageView mIcon;        public TextView mTitle;        public ViewHolder(@NonNull View itemView) {            super(itemView);            mItemView = itemView;            mIcon = itemView.findViewById(R.id.iv_icon);            mTitle = itemView.findViewById(R.id.tv_title);        }    }}

5、为RecyclerView设置LayoutManager

        LinearLayoutManager layoutManager=new LinearLayoutManager(this);        layoutManager.setOrientation(RecyclerView.VERTICAL);        mRecyclerView.setLayoutManager(layoutManager);

6、创建适配器实例,并设置给RecyclerView

        //设置RecyclerView的配器        mAdapter = new MyRecyclerViewAdapter(this);        mRecyclerView.setAdapter(mAdapter);

7、为RecyclerView添加点击事件。

由于RecyclerView本身并没有提供item点击事件,所以需要在Adapter中手动添加

1)第一种方式(高耦合):直接在Viewholder内部类中,或者onBindViewHolder方法中添加点击事件

在ViewHolder类中添加点击事件,需要使用getAdapterPotion()或者getLayoutPosition()获取item位置:

class ViewHolder extends RecyclerView.ViewHolder {        public View mItemView;        public ImageView mIcon;        public TextView mTitle;        public ViewHolder(@NonNull View itemView) {            super(itemView);            mItemView = itemView;            mIcon = itemView.findViewById(R.id.iv_icon);            mTitle = itemView.findViewById(R.id.tv_title);            mItemView.setOnClickListener(new View.OnClickListener() {                @Override                public void onClick(View v) {                    Toast.makeText(mContext, "点击了"+getAdapterPosition(), Toast.LENGTH_SHORT).show();                }            });        }    }

或者onBindViewHOlder方法中添加点击事件,可以直接通过position参数获得item位置:

    public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {        //绑定数据        holder.mTitle.setText(mLists.get(position));        Glide.with(mContext).load(getIcon(position)).into(holder.mIcon);        holder.mItemView.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Toast.makeText(mContext, "点击了"+position, Toast.LENGTH_SHORT).show();            }        });    }

2)第二种方式(低耦合):在Adapter中自定义接口实现点击事件

    private OnItemClickListener mOnItemClickListener;    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {        mOnItemClickListener = onItemClickListener;    }    //定义接口    interface OnItemClickListener {        void onItemClick(int position);    }    ...    public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {        ...        //Item点击事件        holder.mItemView.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                if (mOnItemClickListener != null) {                    mOnItemClickListener.onItemClick(position);                }            }        });    }

实现接口:

        //item点击事件        mAdapter.setOnItemClickListener(new MyRecyclerViewAdapter.OnItemClickListener() {            @Override            public void onItemClick(int position) {                Toast.makeText(MainActivity.this, "第"+position+"数据被点击", Toast.LENGTH_SHORT).show();            }        });

8、切换布局,三种布局循环切换。

//切换布局        mBtnChangeLayout.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                //利用反射获取布局                if (mRecyclerView.getLayoutManager().getClass() == LinearLayoutManager.class) {                    GridLayoutManager gridLayoutManager                            = new GridLayoutManager(MainActivity.this, 2);                    mRecyclerView.setLayoutManager(gridLayoutManager);                } else if (mRecyclerView.getLayoutManager().getClass() == GridLayoutManager.class) {                    StaggeredGridLayoutManager staggeredGridLayoutManager                            = new StaggeredGridLayoutManager(2,                            StaggeredGridLayoutManager.VERTICAL);                    mRecyclerView.setLayoutManager(staggeredGridLayoutManager);                }else{                    LinearLayoutManager layoutManager=new LinearLayoutManager(MainActivity.this);                    layoutManager.setOrientation(RecyclerView.VERTICAL);                    mRecyclerView.setLayoutManager(layoutManager);                }            }        });

在onBindViewHolder方法中,为瀑布流布局设置随机高度:

        //设置瀑布流布局随机高度        if (mRecyclerView.getLayoutManager().getClass() == StaggeredGridLayoutManager.class) {            ViewGroup.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getRandomHeight());            holder.mIcon.setLayoutParams(params);        } else {            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(80, 80);            holder.mIcon.setLayoutParams(params);        }...    private int getRandomHeight() {        return (int) (Math.random() * 1000);    }

9、插入、删除item,并设置动画:

    public void insertData(int position) {        mInsertPosition = position;        mLists.add(position, "插入的数据");        //直接刷新数据,无动画        //notifyDataSetChanged();        //显示插入动画,后面数据的位置不改变,需要手动调用notifyItemRangeChanged更改        notifyItemInserted(position);        //刷新item        notifyItemRangeChanged(position, mLists.size() - position);    }    public void removeData(int position) {        mInsertPosition = -1;        mLists.remove(position);        //直接刷新数据,无动画        //notifyDataSetChanged();        //显示插入动画,后面数据的位置不改变,需要手动调用notifyItemRangeChanged更改        notifyItemRemoved(position);        //刷新item        notifyItemRangeChanged(position, mLists.size() - position);    }

为新插入的item设置单独的背景色

        //为插入的数据设置不同的背景色        if (position == mInsertPosition) {            holder.mItemView.setBackgroundColor(Color.RED);        } else {            holder.mItemView.setBackgroundColor(Color.parseColor("#bbeedd"));        }

 

第二节:NDK入门

一、NDK简介

官方解释:NDK全称是Native Development Kit。NDK是一套允许开发人员将本地代码嵌入Android 应用程序包,可以将Android应用程序中的部分功能用C/C++语言来实现,并将这部分C/C++代码编译成可直接运行在Android平台上的本地代码。这些本地代码以so链接库的形式存在,并能自动将so和java应用一起打包成apk。

通俗解释:NDK允许开发人员用C/C++开发Android程序。

复习:Android四层结构:APP;Framework;基础库、运行时;Linux内核

运行机制:

Java代码->Class文件->ByteCode->Dex(运行与App层)

C代码->.o目标文件->So链接库(运行于Linux内核层)

Jni:Dex中java代码直接调用so链接库。

二、优缺点及使用场景

优点:

• Native代码执行效率高
• 反编译难度大,保密性好
• 可以直接接触底层系统
• Native代码嵌入式平台移植性好
• 方便使用各种开源库

缺点:

• 调用步骤繁琐
• 互调过程开销较大
• 需要处理资源分配与释放
• 要了解的知识更多

使用场景:

  1. 编写 Android 驱动
  2. 对执行效率有高要求
  3. 对底层系统或一些Native开源库有依赖
  4. 代码保密性高

三、NDK的配置

Mac/Linux配置

1、下载NDK

2、命令行:vi ~/.bash_profile

添加一行:export NDK_ROOT="~/...(ndk路径)"

在export PATH="..."中加入:$NDK_ROOT

3、source ~/.bash_profile,使配置生效。

Windows配置

电脑--右键--属性--高级系统设置--环境变量--在系统变量中新建(变量名:NDK_ROOT;变量值:ndk路径)--Path中添加NDK_ROOT

注:ndk使用命令行操作比较方便,cygwin是window下模拟unix的一个工具,推荐使用cygwin操作。

Android Studio的配置

SDK Manager--SDK Tools:NDK前打钩;LLDB前打钩;

Project Structure--SDK location--Android SDK location:选择sdk路径(...SDK\ndk-bundle)

第三节:实战:有声阅读器

Live Template的使用:是一个预定义的代码模板,其中的内容能够根据上下文信息自动推断。AS提供了一些定义好的缩写,如

fori、Toast、todo、psfi等,用户也可以自定义代码模块,如:

单例模式实现:

private volatile static $className$ sInstance;public static $className$ getInstance() {    if (sInstance == null) {        synchronized ($className$.class) {            if (sInstance == null) {                sInstance = new $className$();            }        }    }    return sInstance;}private $className$() {}

弱引用的静态handler

public static class MyHandler extends Handler{        public final WeakReference<$className$> mWeakReference;        public MyHandler($className$ activity) {            mWeakReference=new WeakReference<>(activity);        }        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            $className$ activity = mWeakReference.get();            if(msg.what==$code$){                if(activity!=null){                                    }            }        }    }

*注: 使用 @SerializedName注解,可以解决Gson解析时名称必须相同的问题

*使用GsonFormat插件快速生成实体类

https://blog.csdn.net/zhang_zxk/article/details/84195784

第四节:扩展学习--GIF介绍

更多相关文章

  1. android监控SIM卡状态的广播示例代码
  2. Android(安卓)studio如何使用SVN进行版本控制?
  3. android Toast大全(五种情形)
  4. AndroidUI-TxetView嵌套Html的使用
  5. 在代码中实现按下Home键的效果
  6. android中设置控件边框以及如何保留上或下边框
  7. Android(安卓)瀑布流
  8. webView获取链接后的url和加载经过处理后的HTML
  9. 如何解决软键盘弹出引起的各种不适

随机推荐

  1. Android常用mimetype类型
  2. Android日期对话框
  3. 【Android】共享APK中的资源文件
  4. android dialog 显示时弹出输入法
  5. android SlidingDrawer
  6. android facebook authorize 时禁止调用f
  7. android使用javamail 发送邮件遇到的问题
  8. Android(安卓)studio图片ERROR: 9-patch
  9. Android:在WebView中获取网页源码
  10. android 按钮按下时改变字体颜色