第5章 activity间数据的传递
关于创建和启动新的activity
Android Studio下新建activity似乎没有eclipse下的子activity的从属的概念。每一个activity之间,除了launcher activity,似乎都是平行的,没有谁一定属于谁,只有相互调用的关系。
在一个activity中调用另一个activity时,是将调用请求发送给操作系统的ActivityManager,ActivityManager根据接收到的Intent参数(类似于Windows编程中的句柄??)来创建activity实例。
有关activity之间的值传递
这和onSaveInstanceState()方法类似,都是将要传递的信息映射到字符串键上。在activity之间传递数据要用intent extra。将extra的信息添加给intent的方法为intent.putExtra(),类比savedInstaceState.putXXX()。获取extra信息的方法为getXXXExtra(),类比savedInstaceState.getXXX()。
主activity向子activity传递数据的过程是:先实例化一个intent对象并将需要传递的数据存储进intent,然后使用该intent和专门的请求代码来向ActivityManager申请创造子activity,最后新建的子activity可以解析传递来的extra。
子activity向主activity传递数据的过程是:实例化intent对象并将需要传递的数据存储进intent,然后调用setResult()方法将结果打包,主activity会根据之前的请求代码来调用onActivityResult()方法,解析传回来的结果。解析的过程不做细致描述。
我今天在尝试的时候,发现点击完作弊之后主Activity没有接收到任何作弊提示,原因就是在于没有将Intent参数传入setResult()方法中。
在onActivityResult()方法要注意请求代码是否匹配,返回代码是否符合预期(OK/CANCEL),因为“实践证明,这样做会方便将来代码的维护”。
有关tools与tools:text
这个tools感觉就是在开发过程中使用的可以预先实现一些功能的工具,很像存根程序或驱动程序。这个帖子详细地讲解了tools的作用。
这里的tools:text是覆盖掉这个控件的Android:text,并且使得text内的内容在预览时可见而在实际运行时不可见。
有关挑战练习:堵住漏洞
用户作弊后,可以旋转CheatActivity来清除作弊痕迹
同一个activity内在旋转屏幕前后要保存数据,就如同之前的做法一样将数据保存到一个键值对里面,在重写onSaveInstanceState()方法存储就可以了。
定义一个成员变量来记录此次activity是否作弊了(点击查看答案按钮)。
private boolean mCheated;
protected void onSaveInstanceState(Bundle saveInstanceState)
{
super.onSaveInstanceState(saveInstanceState);
saveInstanceState.putBoolean(KEY_CHEAT,mCheated);
}
之前一直纠结要不要给成员变量初始化的问题,其实不需要,因为在再次接受mCheated时,如果其为空会给它缺省值。
mCheated=savedInstanceState.getBoolean(KEY_CHEAT,false);
每次通过解析得到mCheat时,要重新调用setAnswerShownResult();方法将结果写入extra中,并且判断是否已经作弊了,由此来决定文本框内容。
if (savedInstanceState!=null)
{
mCheated=savedInstanceState.getBoolean(KEY_CHEAT,false);
setAnswerShownResult(mCheated);
if (mCheated)
{
if (mAnswerIsTrue)
{
mAnswerTextView.setText(R.string.true_button);
}
else
{
mAnswerTextView.setText(R.string.false_button);
}
}
}
作弊返回后,用户可以旋转QuizActivity来清除mIsCheated变量值
同上。
用户可以不断单击NEXT按钮,跳到偷看过答案的问题,从而使作弊记录丢失
这个问题是怎么来的呢?因为先前每一次点击next按钮时,mIsCheated默认被赋值为false,只要点击next其值就会被自动刷新为false。
参考当时处理此题是否被回答过的情况,完全一样的做法,给question类再增加一个成员变量,每一次点击next时,根据题目编号来赋值mIsCheated。
public class Question {
private int mTextResId;
private boolean mAnswerTrue;
private boolean mAnswered;
private boolean mIsCheated;
public Question(int TextResId, boolean AnswerTrue,boolean Answered,boolean IsCheated)
{
mTextResId=TextResId;
mAnswerTrue=AnswerTrue;
mAnswered=Answered;
mIsCheated=IsCheated;
}
//...
}
再将是否作弊的结果保存到键值对里面即可。
每一次作弊完之后都要更新这个成员变量。我在试验时发现好像还是没成功。。。因为我没把是否作弊的结果存到数组里面。。
@Override
protected void onActivityResult(int requestCode,int resultCode,Intent data)
{
if (resultCode!=RESULT_OK)
{
return;
}
if (requestCode==REQUEST_CODE_CHEAT)
{
if (data==null)
{
return;
}
mIsCheater=CheatActivity.wasAnswerShown(data);
//此处一定要更新
mQuestionBank[mCurrentIndex].setCheated(mIsCheater);
}
}