Activities
多activity的合作
当activity A启动activity B时,两个activity生命周期如下:
-
- Activity A的 onPause()方法,如果活动后台不可见的话,onStop()方法同样运行,否则不运行。
- Activity B的 onCreate() ,onStart() 和onResume() 方法依次运行。(Activity B现在获得用户焦点。)
以上预设的生命周期回调方法顺序使你能够对一个activity启动另一个activity时的转换信息进行管理。 例如,如果第一个activity停止时你须写入数据库以便后续的activity可以读取数据,那么你应该在 onPause() 方法而不是 onStop() 方法里写入数据库。防止数据还未准备完毕时activity B就已经启动。
Fragments
Fragment表现Activity中用户界面的一个行为或者是一部分。你可以在一个单独的activity上把多个fragment组合成为一个多区域的UI,并且可以在多个activity中再使用。你可以认为fragment是activity的一个模块零件,它有自己的生命周期,接收它自己的输入事件,并且可以在activity运行时添加或者删除。
fragment的生命周期与和他绑定的activity息息相关。且和activity一样,可以通过onSaveInstanceState()方法保存状态。
创建fragment需要继承fragment父类或者fragment父类的子类
onCreate()
- 同activity一样,可以在此方法中初始化一些需要的数据和控件等等。
onCreateView()
- 在第一次为fragment绘制用户界面时系统会调用此方法。为fragment绘制用户界面,这个函数必须要返回所绘出的fragment的根View。如果fragment没有用户界面可以返回空。
onPause()
当用户离开fragment,第一个调用的方法,并不意味着此fragment一定会被销毁,但是很有可能用户不会再进入此界面,所以同activity一样,需要在此生命周期里做数据持久化操作。(同多activity的合作一样)
处理Fragment事务
在activity中使用fragment特点:可以任意添加、删除、替换、执行、响应用户交互。使用例如add()、remove()、replace()等方法设置相关事务,然后通过commit()方法提交给activity。提交给activity之后并不意味着立即执行,而是 进行预约等待,知道主线程准备完毕才可运行。(调用executePendingTransations()方法可立即执行,但是一般不推荐)。
假设用户离开activity时,刚好commit()了一个fragment的事务,此时会抛出异常(爹都跑了儿子还玩个P),此时如果activity被恢复,那么commit之后的状态将丢失。如果存在这种情况,使用commitAllowingStateLoss(),提前告诉你儿子,你可能会走,在原地等我。
与Activity交互
当创建了一个fragment实例之后,此fragment就会与对应的activity进行绑定,确认父子关系,fragment可以通过getactivity()方法获取与之绑定的activity,从而可以通过唯一的id获取activity中的view。反之activity也能通过getFragmentManager().findFragmentById获取fragment。
创建activity事件回调函数
假设点击fragment中某一按钮需要在activity中显示对应的信息,需要在此fragment中定义一个回调的接口,然后在宿主activity中实现此接口,当调用fragment中的onclick方法时,调用此接口的方法,就可以将信息传递给自己。(实战中大多通过activity传递给另外一个fragment)。
public class Fragment extends android.app.Fragment { EditText editText; Button button; onCallback oncallback; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment,null); editText = (EditText)view.findViewById(R.id.edit_query); button = view.findViewById(R.id.button3); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { getText(oncallback); } }); return view; } @Override public void onAttach(Activity activity) { super.onAttach(activity); try { oncallback = (onCallback) activity; }catch (Exception o){ } } public void getText(onCallback oncallback){ String text = editText.getText().toString(); if (text == null){ text = "null"; } oncallback.doThings(text); } public interface onCallback{ public void doThings(String text); } }
public class MainActivity extends Activity implements View.OnClickListener { private TextView textView = null; FragmentManager fragmentManager; FragmentTransaction fragmentTransaction; Fragment fragment; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = (TextView)findViewById(R.id.text); fragmentManager = getFragmentManager(); fragmentTransaction = fragmentManager.beginTransaction(); fragment =new Fragment(); fragment.oncallback = new Fragment.onCallback() { @Override public void doThings(String text) { textView.setText(text); } }; fragmentTransaction.add(R.id.fragment,fragment); fragmentTransaction.commit(); } }
添加items到Action Bar
需要在fragment的oncreate()方法中调用setHasOptionsMenu(Boolean)方法将此属性设置为true,否则后面将不会回调onCreateOptionsMenu()方法,也就不会调用onOptionsItemSelected()方法。
Tasks and Back Stack
一个程序含有很多个activity,每个activity设计时都应该以执行某一个用户发起的action为核心目标(例如app的main activity就是执行了
"android.intent.action.MAIN"
这一个action),且能够启动其他activity(startactivity等方法)。或者定义一个特定的携带action的intent来启动在Androidmanifest中定义了此action的activity。很多时候可能有很多个activity都带有同一个action参数,此时,系统会让用户选择一个来打开。
通过action打开的activity即使和打开它的activity不属于同一个应用,也将存在同一个task中。默认将压入同一个栈中(按照启动顺序后进先出。)也可以在启动的时候设置flag来选择如何启动activity。
可以使用的 <activity> 属性主要有:
可用的 intent 标志主要有:
- FLAG_ACTIVITY_NEW_TASK 如果activity不存在,在一个新的栈中启动,否则就将那个task调入前台显示
- FLAG_ACTIVITY_CLEAR_TOP 清除启动的activity之上所有activity,并重新启动activity
- FLAG_ACTIVITY_SINGLE_TOP 如果启动的activity不在栈顶,则在新的栈中启动
使用 manifest 文件
launchMode 属性指明了 activity 启动 task 的方式。 launchMode 属性可设为四种启动模式:
-
"standard" (默认模式)
- 默认值。系统在启动 activity 的 task 中创建一个新的 activity 实例,并把 intent 传送路径指向它。该 activity 可以被实例化多次,各个实例可以属于不同的 task,一个 task 中也可以存在多个实例。
-
"singleTop"
- 如果 activity 已经存在一个实例并位于当前 task 的栈顶,则系统会调用已有实例的 onNewIntent()方法把 intent 传递给已有实例,而不是创建一个新的 activity 实例。activity 可以被实例化多次,各个实例可以属于不同的 task,一个 task 中可以存在多个实例(但仅当 back stack 顶的 activity 实例不是该 activity 的)。
-
"singleTask"
- 如果此activity已经存在,则调用该activity否则新起一个task来启动此activity。 此 activity 同一时刻只能存在一个实例。
-
"singleInstance"
- 除了系统不会把其它 activity 放入当前实例所在的 task 之外,其它均与 "singleTask"相同。activity 总是它所在 task 的唯一成员;它所启动的任何 activity 都会放入其它 task 中。