前言
因为之前没有写笔记的习惯,所以今天(2024年7月31日)先把之前所学习的知识粗略的概括一下,从明天开始就要正式写笔记了
实际上是本章及其之前的知识汇总
由于本书较老,与新版有许多区别
我在学习的过程中因为导入库代码的改动对我造成了较大的阻碍
因为这似乎是一个很新的操作,我在寻找解决方法时包括我询问Chat-GPT得到的答案都与书中相同,为旧版添加
我在懵懵懂懂的过程中以某种不知为何的状态点击Android studio中的报错提示修改却又得以运行
后来我通过尽可能新的教学视频得知
不仅仅需要修改build.gradle.kts文件
还需要在libs.versions.toml文件中进行修改
具体如何修改视频并没有细说,但这也解答了我的一个疑惑
使我清除了学习路上的一大阻力
Activity(活动)的生命周期
-
onCreate():这个方法你已经看到过很多次了,每个活动中我们都重写了这个方法,它会在活动第一次被创建的时候调用。你应该在这个方法中完成活动的初始化操作,比如 说加载布局、绑定事件等。
-
onStart():这个方法在活动由不可见变为可见的时候调用。
-
onResume():这个方法在活动准备好和用户进行交互的时候调用。此时的活动一定位于返回栈的栈顶,并且处于运行状态。
-
onPause():这个方法在系统准备去启动或者恢复另一个活动的时候调用。我们通常会在 这个方法中将一些消耗 CPU 的资源释放掉,以及保存一些关键数据,但这个方法的执行速度一定要快,不然会影响到新的栈顶活动的使用。
-
onStop():这个方法在活动完全不可见的时候调用。它和 onPause()方法的主要区别在于,如果启动的新活动是一个对话框式的活动,那么 onPause()方法会得到执行,而 onStop()方法并不会执行。
-
onDestroy():这个方法在活动被销毁之前调用,之后活动的状态将变为销毁状态。
-
onRestart():这个方法在活动由停止状态变为运行状态之前调用,也就是活动被重新启动了
//以下是在查阅稀金社区时看到的别人的解释,似乎更加便于理解
以上 7 个方法中除了 onRestart()方法,其他都是两两相对的,从而又可以将活动分为 3 种生存期。
完整生存期:活动在 onCreate()方法和 onDestroy()方法之间所经历的,就是完整生存 期。一般情况下,一个活动会在 onCreate()方法中完成各种初始化操作,而在 onDestroy()方法中完成释放内存的操作。
可见生存期:活动在 onStart()方法和 onStop()方法之间所经历的,就是可见生存期。 在可见生存期内,活动对于用户总是可见的,即便有可能无法和用户进行交互。我们可 以通过这两个方法,合理地管理那些对用户可见的资源。比如在 onStart()方法中对资 源进行加载,而在 onStop()方法中对资源进行释放,从而保证处于停止状态的活动不会占用过多内存。
前台生存期:活动在 onResume()方法和 onPause()方法之间所经历的就是前台生存期。 在前台生存期内,活动总是处于运行状态的,此时的活动是可以和用户进行交互的,我 们平时看到和接触最多的也就是这个状态下的活动
活动的启动模式
//修改活动的启动模式
android:launchMode="singleTop"
standard
standard 是活动默认的启动模式,在不进行显式指定的情况下,所有活动都会自动使用这种启动模式。
在 standard 模式(即默认情况)下,每当启 动一个新的活动,它就会在返回栈中入栈,并处于栈顶的位置。对于使用 standard 模式的活动, 系统不会在乎这个活动是否已经在返回栈中存在,每次启动都会创建该活动的一个新的实例。
singleTop
当活动的启动模式指定为 singleTop,在启动活动时如果发现返回栈的栈顶已经是该活动,则认为可以直接使用它,不会再创建新的活动实例。
singleTask
当活动的启动模式指定为 singleTask,每次启动该活动时系统首先会在返回栈中检查是否 存在该活动的实例,如果发现已经存在则直接使用该实例,并把在这个活动之上的所有活动统统出栈,如果没有发现就会创建一个新的活动实例。
singleInstance
指定为 singleInstance 模式的活动会启用一个新的返回栈来管理这个活动(其实如果 singleTask 模式指定了不同的 taskAffinity,也会启动一个新的返 回栈)。
新建一个栈来管理这个活动,
1启动2 ,2在返回栈B中
2启动3,3在返回栈A中
3按返回会回到1而不是2
而1按返回回到2
在按返回就退出程序了
RecyclerView
1.重写的三个方法
第一次遇到这种情况便是与RecyclerView 的第一次相遇
书上说需要再build.gradle文件中添加如下代码
compile 'com.android.support:recyclerview-v7:24.2.1'
添加后会报错
根据我的摸索是在build.gradle文件中添加如下代码
implementation(libs.recyclerview)
并且在libs.versions.toml文件中添加如下代码
recyclerview = { group = "androidx.recyclerview", name = "recyclerview", version.ref = "recyclerview" }
才可使用
RecyclerView的使用必须创建一个Adapter.java类
在该类中重写以下三个方法
@NonNull
@Override public RecyclerViewAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(this.context).inflate(R.layout.textview_layout,parent,false);
return new MyViewHolder(view);
}
@Override public void onBindViewHolder(@NonNull RecyclerViewAdapter.MyViewHolder holder, int position) {
holder.textView.setText(str.get(position));
}
@Override public int getItemCount() {
return str.size();
}
其中onCreateViewHolder方法是为每一个Item指定layout
onBindViewHolder方法则是使数据进行填充显示
getItemCount方法是得到需要显示的长度
这是必须重写的三个方法
2.点击事件注册
Adapter.java
static class ViewHolder extends RecyclerView.ViewHolder {
View fruitView;
ImageView fruitImage;
TextView fruitName;
public ViewHolder(View view){
super(view);
fruitView = view;
fruitImage =(ImageView)view.findViewById(R.id.fruit_image);
fruitName =(fextView)view.findViewById(R.id.fruit_name);
}
}
public FruitAdapter(List<Fruit> fruitList){
mFruitList = fruitList;
}
@override
public ViewHolder onCreateViewHolder(ViewGroup parent,int viewType){
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.
fruit_item,parent,false);
final viewHolder holder = new ViewHolder(view);
holder.fruitView.setOnClickListener(new View.OnclickListener(){
@0verride
public void onclick(View v){
int position = holder.getAdapterPosition();
Fruit fruit = mFruitList.get(position);
Toast.makeText(v.getContext(),"you clicked view " + fruit.getName(),
Toast.LENGTH_SHORT).show();
}
});
holder.fruitImage.setOnclickListener(new View.OnclickListener(){
@Override
public void onclick(View v){
int postition = holder.getAdapterPosition();
Fruit fruit = mFruitList.get(position);
Toast.makeText(v.getContext(),"you clicked image "+ fruit.getName(),
Toast.LENGTH_SHORT).show();
}
});
return holder;
在 ViewHolder 中添加了 fruitView 变量来保存子项最外层布局的实例
然后在 onCreateViewHolder()方法中注册点击事件
这里分别为最外层布局和 ImageView 分别注册点击事件(当前项目与项目中的图片),
RecyclerView 可以轻松实现子项中任意控件或布局的点击事件。
我们在两个点击事件中先获取了用户点击的 position,然后通过 position 拿到相应的 Fruit 实例,再使用 Toast 分别弹出两种不同的内容以示区别
制作 Nine-Patch 图片(待续)
这部分由于新版与书中不同,并且还未找到新版的使用方式,所以暂时搁置,后续发现进行补充
Fragment(碎片)
碎片的生命周期
-
运行状态:当一个碎片是可见的,并且它所关联的活动正处于运行状态时,该碎片也处于运行状态。
-
暂停状态:当一个活动进入暂停状态时(由于另一个未占满屏幕的活动被添加到了栈顶),与它相关联 的可见碎片就会进入到暂停状态。
-
停止状态:当一个活动进入停止状态时,与它相关联的碎片就会进入到停止状态,或者通过调用FragmentTransaction 的 remove()、replace()方法将碎片从活动中移除,但如果在事务提交之 前调用 addToBackStack()方法,这时的碎片也会进入到停止状态。总的来说,进入停止状态的 碎片对用户来说是完全不可见的,有可能会被系统回收。
-
销毁状态:碎片总是依附于活动而存在的,因此当活动被销毁时,与它相关联的碎片就会进入到销毁状态。或者通过调用 FragmentTransaction 的 remove()、replace()方法将碎片从活动中移除,但 在事务提交之前并没有调用 addToBackStack()方法,这时的碎片也会进入到销毁状态。
Fragment 类中也提供了 一系列的回调方法,以覆盖碎片生命周期的每个环节。其中,活动中有的回调方法,碎片中几乎都有,不过碎片还提供了一些附加的回调方法,重点看一下这几个回调。
-
onAttach():当碎片和活动建立关联的时候调用。
-
nCreateView():为碎片创建视图(加载布局)时调用。
-
onActivityCreated():确保与碎片相关联的活动一定已经创建完毕的时候调用。
-
onDestroyView():当与碎片关联的视图被移除的时候调用。
-
onDetach():当碎片和活动解除关联的时候调用。
碎片的使用方式
新建一个左侧碎片布局 left_fragment.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Button"
/>
</LinearLayout>
然后新建右侧碎片布局 right_fragment.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:background="#00ff00"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="20sp"
android:text="This is right fragment"
/>
</LinearLayout>
接着新建一个 LeftFragment 类,并让它继承自 Fragment。注意,这里可能会有两个不同包 下的 Fragment 供你选择,一个是系统内置的 android.app.Fragment,一个是 support-v4 库中的 android.support.v4.app.Fragment。这里我强烈建议你使用 support-v4 库中的 Fragment,因为它可 以让碎片在所有 Android 系统版本中保持功能一致性。
LeftFragment 类
public class LeftFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.left_fragment, container, false);
return view;
}
}
新建一个 RightFragment
public class RightFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.right_fragment, container, false);
return view;
}
}
接下来修改 activity_main.xml 中的代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="@+id/left_fragment"
android:name="com.example.fragmenttest.LeftFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<fragment
android:id="@+id/right_fragment"
android:name="com.example.fragmenttest.RightFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
这样最简单的碎片就写好了