Activity
一,Activity生命週期
onCreate()
創建Activity時被回調。
該方法做一些初始化動作,比如創建views,設置數據到list等等。
這個方法提供了一個Bundle類型的變量,該變量中有這個activity以前存儲過的狀態信息。
若在onCreate方法中加入finish()方法,onCreate下一個運行onDestory方法。
此時Activity還在後臺,不可見。
onStart()
啓動Activity時被調用。
當activity在前臺顯示時,會運行onResume。
當activity還沒在前臺顯示就被隱藏(停止狀態)了會運行onStop(),比如在onStart方法中用了finish()方法的話,onStart()之後就會直接運行onStop→onDestory。
此時Activity已經可見了,但是還沒出現在前臺,我們還看不到,無法與Activity交互。
onResume()
恢復Activity時被回調,並且爲了用戶操作此時該activity位於activity棧的頂部。經過某些操作後該方法執行完後執行的是onPause()。
Activity在這個階段已經出現在前臺並且可見了。這個階段可以打開獨佔設備。
onPause()
暫停Activity時被回調。
當Activity要跳到另一個Activity或應用正常退出時都會執行這個方法。此時Activity在前臺並可見,我們可以進行一些輕量級的存儲數據和去初始化的工作,不能太耗時,因爲在跳轉Activity時只有當一個Activity執行完了onPause方法後另一個Activity纔會啓動,而且android中指定如果onPause在500ms即0.5秒內沒有執行完畢的話就會強制關閉Activity。從生命週期圖中發現可以在這快速重啓,但這種情況其實很罕見,比如用戶切到下一個Activity的途中按back鍵快速得切回來。
onStop()
停止Activity時被回調。
一個新的activity被執行,一個存在的activity被切換到最前端,這個activity要被銷燬。都會觸發onStop()方法。
如果用戶召回這個activity,那麼會調用onRestart方法。
如果用戶銷燬這個activity,那麼會調用onDestory方法。
此時Activity已經不可見了,但是Activity對象還在內存中,沒有被銷燬。這個階段的主要工作也是做一些資源的回收工作,用戶退出程序,建議在onStop方法中保存數據。
onDestory()
銷燬Activity時被回調。
activity調用了finish()方法來結束這個activity或者因爲系統爲了節省空間而臨時銷燬這個activity,這兩個情況可以通過isFinishing()方法判斷。
這個階段Activity被銷燬,不可見,我們可以將還沒釋放的資源釋放,以及進行一些回收工作。
onRestart()
重啓Activity時被調用。該方法優先於再次運動的onStart,運行完onRestart之後運行onStart。
在該方法中加入finish()語句,則還會繼續運行onStart及後面狀態方法直到onDestroy運行完成。
Activity在這時可見,當用戶按Home鍵切換到桌面後又切回來或者從後一個Activity切回前一個Activity就會觸發這個方法。這裏一般不做什麼操作。
二,生命週期之間的區別
onCreate和onStart
(1)可見與不可見的區別。前者不可見,後者可見。
(2)執行次數的區別。onCreate方法只在Activity創建時執行一次,而onStart方法在Activity的切換以及按Home鍵返回桌面再切迴應用的過程中被多次調用。因此Bundle數據的恢復在onStart中進行比onCreate中執行更合適。
(3)onCreate能做的事onStart其實都能做,但是onstart能做的事onCreate卻未必適合做。如前文所說的,setContentView和資源初始化在兩者都能做,然而想動畫的初始化在onStart中做比較好。
onStart和onResume
(1)是否在前臺。onStart方法中Activity可見但不在前臺,不可交互,而在onResume中在前臺。
(2)職責不同,onStart方法中主要還是進行初始化工作,而onResume方法,根據官方的建議,可以做開啓動畫和獨佔設備的操作。
onPause和onStop
(1)是否可見。onPause時Activity可見,onStop時Activity不可見,但Activity對象還在內存中。
(2)在系統內存不足的時候可能不會執行onStop方法,因此程序狀態的保存、獨佔設備和動畫的關閉、以及一些數據的保存最好在onPause中進行,但要注意不能太耗時。
onStop和onDestroy
onStop階段Activity還沒有被銷燬,對象還在內存中,此時可以通過切換Activity再次回到該Activity,而onDestroy階段Acivity被銷燬。
三,Activity配置
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
四,啓動Activity
直接啓動
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
StartActivity(intent);
或
Intent intent = new Intent();
ComponentName component = new ComponentName( MainActivity.this,SecondActivity.class);
intent.setComponent(component);
startActivity(intent);
匿名啓動
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="test"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
Intent intent = new Intent();
intent.setAction("test");
startActivity(intent);
五,Activity之間的數據交換
putExtra
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
intent.putExtra("name","db");//以鍵值對的方式傳遞
StartActivity(intent);
在SecondActivity的代碼中獲取數據
Intent intent = getIntent();
if(intent!=null)
{
String name = intent.getStringExtra("name");
}
putString
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
Bundle bundle = new Bundle();
bundle.putString("name","db");
intent.putExtras(bundle);
StartActivity(intent);
//在SecondActivity的代碼中獲取數據和方法一相同
putSerializable
public class User implements Serializable{
private String name;
private int age;
public User(String name,int age)
{
this.name = name;
this.age = age;
}
}
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
User user = new User("db",20);
Bundle bundle = new Bundle();
bundle.putSerializable("User",user);
intent.putExtras(bundle);
StartActivity(intent);
在SecondActivity的代碼中獲取數據
Intent intent = getIntent();
if(intent!=null)
{
User user = (User)intent.getSerializableExtra("User");
}
Fragement
Fragment是可以讓你的app縱享絲滑的設計,如果你的app想在現在基礎上性能大幅度提高,並且佔用內存降低,同樣的界面Activity佔用內存比Fragment要多,響應速度Fragment比Activty在中低端手機上快了很多,甚至能達到好幾倍!如果你的app當前或以後有移植平板等平臺時,可以讓你節省大量時間和精力。
一,Fragement的優點
- Fragment可以使你能夠將activity分離成多個可重用的組件,每個都有它自己的生命週期和UI。
- Fragment可以輕鬆得創建動態靈活的UI設計,可以適應於不同的屏幕尺寸。從手機到平板電腦。
- Fragment是一個獨立的模塊,緊緊地與activity綁定在一起。可以運行中動態地移除、加入、交換等。
- Fragment提供一個新的方式讓你在不同的安卓設備上統一你的UI。
- Fragment 解決Activity間的切換不流暢,輕量切換。
- Fragment 替代TabActivity做導航,性能更好。
- Fragment 在4.2.版本中新增嵌套fragmeng使用方法,能夠生成更好的界面效果。
- Fragment做局部內容更新更方便,原來爲了到達這一點要把多個佈局放到一個activity裏面,現在可以用多Fragment來代替,只有在需要的時候才加載Fragment,提高性能
二,Fragement的生命週期
onAttach() | 當Fragment被添加到Activity時被調用,該方法只會被調用一次。需要注意的是,初始化fragment參數可以從getArguments()獲得,但是,當Fragment附加到Activity之後,就無法再調用setArguments()。 |
onCreate(Bundle) | 創建Fragment時被回調。該方法只會被調用一次。此時的Activity還沒有創建完成,因爲我們的Fragment也是Activity創建的一部分。所以如果你想在這裏使用Activity中的一些資源,將會獲取不到。 |
onCreateView() | 每次創建、繪製Fragment的View組件都會調用。 |
onActivityCreated() | 當Fragment所在的Activity被啓動完成後調用。所以到這裏的時候,Activity已經創建完成!在這個函數中才可以使用Activity的所有資源。如果把下面的代碼放在這裏,獲取到的btn_Try的值將不會再是空的! |
onStart() | 當Fragment即將可見時調用。在生命週期中也可以看到Fragment的OnStart()過程與Activity的OnStart()過程是綁定的。 |
onResume() | 當Fragment即將獲得焦點時調用。從生命週期對比中,可以看到,Fragment的OnResume與Activity的OnResume是相互綁定的,意義是一樣的。它依賴於包含它的activity的Activity.onResume。當OnResume()結束後,就可以正式與用戶交互了。 |
onPause() | 由活動狀態變成暫停狀態時調用,與Activity的OnPause()意義一樣。 |
onStop() | 不可見時調用,進入停止狀態。這個回調與Activity的OnStop()相綁定,意義一樣。已停止的Fragment可以直接返回到OnStart()回調,然後調用OnResume()。 |
onDestroyView() | 銷燬View組件時調用,在onStop()之後,onDestroy()之前調用。 |
onDestroy() | Fragment對象銷燬時調用。需要注意的是,它即使經過了onDestroy()階段,但仍然能從Activity中找到,因爲它還沒有Detach。 |
onDetach() | Fragment與Activity分離時調用。調用它以後,Fragment就不再與Activity相綁定,它也不再擁有視圖層次結構,它的所有資源都將被釋放。 |
三,創建Fragment
一,定義兩個Fragement的佈局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00ff00" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is fragment 1"
android:textColor="#000000"
android:textSize="25sp" />
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0090FF" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is fragment 1"
android:textColor="#000000"
android:textSize="25sp" />
</LinearLayout>
二,自定義Fragment類
需要繼承Fragment或者他的子類,重寫onCreateView()方法 在該方法中調用:inflater.inflate()方法,加載Fragment的佈局文件,接着返回加載的view對象,我們分別創建兩個fragment的佈局。
import androidx.fragment.app.Fragment;
public class Fragement1 extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragement1, container,false);
return view;
}
}
==================================
public class Fragement2 extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragement1, container,false);
return view;
}
}
三,在Activity對應的佈局文件中添加fragment的標籤
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false" >
<fragment
android:id="@+id/fragment1"
android:name="com.zzu.sunshaoqi.myapplication.Fragement1"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1" />
<fragment
android:id="@+id/fragment2"
android:name="com.zzu.sunshaoqi.myapplication.Fragement2"
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
四,調用setContentView()
import androidx.fragment.app.FragmentActivity;
public class MainActivity extends FragmentActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:baselineAligned="false" >
<Button
android:id="@+id/btn_show_fragment1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="顯示Fragment1"/>
<Button
android:id="@+id/btn_show_fragment2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="顯示Fragment2"/>
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
public class MainActivity extends FragmentActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnLoadFrag1 = (Button) findViewById(R.id.btn_show_fragment1);
btnLoadFrag1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
Fragement1 fragment1 = new Fragement1();
transaction.add(R.id.fragment_container, fragment1);
transaction.commit();
}
});
Button btnLoagFrag2 = (Button)findViewById(R.id.btn_show_fragment2);
btnLoagFrag2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
Fragement2 fragment2 = new Fragement2();
transaction.add(R.id.fragment_container, fragment2);
transaction.commit();
}
});
}
}