2021SC@SDUSC
前言
本篇开始分析飞花令项目的源码。飞花令的项目要求实现两个主要功能,一个是查询所有包含输入关键字的诗句,一个是人机模拟飞花令游戏。 本篇将继续分析飞花令小游戏的代码。一、项目环境
android studio 4.1.2
Compile SDK version:30
Build Tools Version 30.0.3
gradle 6.8.3
二、代码分析
1.两个页面之间的过渡部分
从查询到飞花令两个页面之间的过渡部分,用语言描述来说:在查询页面点击“飞花令”的按钮之后,跳转到飞花令的页面,并且获得由查询页面传过来的参数——即关键字,根据关键字检索到相应诗句之后开始飞花令的第一句,由此继续。
其中有一点就是关键字的传递,即两个activity中间参数传递的过程,所以在这里整理了一下参数传递的方法。
直接传递:
直接传递是指Activity直接向另外一个Activity传递参数,例如开发中:需要A、B两个Activity,A启动B,而且B需要A在A中所处理的业务逻辑结果进行相应的改变以及一些视图或者业务逻辑上的处理等需求时所采用的数据传递。
putExtra(“A”,B)方法:AB为键值对,第一个参数为键名,第二个参数为键对应的值。如果想取出Intent对象中的这些值,需要在你的另一个Activity中用getXXXXXExtra方法,注意需要使用对应类型的方法,参数为键名
1)直接使用Intent:
源Activity中: MainActivity.java中:
Intent intent = new Intent();
intent.putExtra("text", myTextView.getText());类似于key—value键值对
intent.setClass(MainActivity.this, Activity2.class);
//从第一个参数传到第二个参数
startActivity(myIntent);
第二个activity: Activity2.java中:
//从MainActiviry中跳转到这个Activity中利用Intent传递数据。
//获取Intent
Intent intent = getIntent();
String text = intent.getStringExtra("myText");
2)使用Bundle传递数据:
在当前的activity中new一个Bundle对象,在这个对象中putString,然后把这个Bundle作为数据putExtra到Intent里,然后再目标activity中getExtra拿到Bundle对象,再getString获得Bundle中的数据。
源Activity中:MainActivity.java
//使用Bundle传递参数到另一个Activity
Intent myIntent = new Intent();
Bundle bundle = new Bundle();
bundle.putString("info",myEditText.getText().toString());
myIntent.putExtras(bundle);
myIntent.setClass(MainActivity.this, Activity3Bundle.class);
startActivity(myIntent);
目标Activity:Activity_Bundle.java
Bundle myBundle = this.getIntent().getExtras();
String myText = myBundle.getString("info");
同时,上述两种方法都可以与点击按钮/链接等相结合。
可以看到该项目中使用了第二种传参的方法 ,利用Bundle来传递参数
private Button start;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
start = findViewById(R.id.button1);
start.setOnClickListener(new View.OnClickListener() {//与按钮点击联系起来
@Override
public void onClick(View view) {
EditText key= findViewById(R.id.id_key);//存放参数
Intent intent = new Intent(MainActivity.this,MainActivity2.class);
System.out.println(key.getText().toString());
Bundle bundle = new Bundle();
bundle.putString("data",key.getText().toString());
intent.putExtras(bundle);
startActivity(intent);
}
});
}
2.飞花令ui界面
软件开发人员设计的⻜花令的UI界面和聊天界⾯很类似,人机各占一边,分别一人一句,界面下面是关键字的提示、输入框和提交按钮,上边是诗句展示页面。
在activity_main2.xml⾥添加EditText,Button,ListView控件:
ListView用于展示,EditText用于输入诗句,Button发送按钮
由于类似于聊天界面,由电脑和用户分别发出消息,位于左端和右端,要将两边消息区分开,开发人员利用了变量赋值不同来加以区分
public class Msg {
public static final int TYPE_RECEIVED = 0;
public static final int TYPE_SEND = 1;
private String content;
并且建立适配器MsgAdapter
public MsgAdapter(Context context, int textViewResourceId, List<Msg> objects) ;//三个参数:上下文环境、布局文件、数据源
public View getView(int position, View convertView, ViewGroup parent) {返回给安卓系统一个视图 position:该视图在适配器数据中的位置 convertView:旧视图 parent: 此视图最终会被附加到的父级视图
Msg msg = getItem(position);//获得相应数据集合中特定位置即position对应的Msg对象
View view;
ViewHolder viewHolder;
ViewHolder是一个新出现的类,也是Android中一个重要的知识点
ViewHolder
ViewHolder通常出现在适配器里,为的是listview滚动的时候快速设置值,而不必每次都重新创建很多对象,从而提升性能。ViewHolder是一个静态类,可以用于保存每行的视图以避免每次调用getView时都会调用findViewById(),从而起到优化适配器的作用
convertView是缓存的View,即BaseAdapter回收机制里的那个View,当第一次需要从里边拿ImageView的时候,里边是空的,需要实例化一个,不空的时候就可以直接拿来用了。
ViewHolder是自己定义的类:
LinearLayout称作线性布局,ViewHolder分别定义了左侧和右侧的布局和两个TextView框。
class ViewHolder {
LinearLayout leftLayout;
LinearLayout rightLayout;
TextView leftMsg;
TextView rightMsg;
}
我的理解是convertView是一个缓存池,它的大小决定了可以存放多少个view的item,而new的view个数小于其大小的时候,当有新的item出现的时候需要继续实例化,而等于大于其大小的时候,即convertView!=null时,利用ViewHolder实行View的复用,即“使用convertView主要是为了缓存试图View,用以增加ListView的item view加载效率。在Adapter的getView中,先判断convertView是否为空null,如果非空,则直接再次对convertView复用,否则才创建新的View。“
定义了一个tagId,用以标记convertView,在新创建的convertView里面打入进去,然后在后续convertView复用时候取出来,以追踪此时复用的到底是哪个convertView。这时候就是setTag()方法和getTag()方法。View中的setTag(Onbect)表示给View添加一个格外的数据,以后可以用getTag()将这个数据取出来。这两个方法在一些需要用到Adapter自定控件显示方式的时候非常有用,可以使用setTag把查找的view缓存起来方便多次重用。
三、总结
今天主要了解了ViewHolder类和Activity中参数的传递,感觉Android开发中的缓存机制和这种系统性的包装和嵌套结构非常有趣。