標籤:des android blog http io os 使用 java ar
前言學習Java和Android將近一年的時間了,期間的成果應該就是獨立完成了一個Android用戶端“玩機攻略”,並且保證了其在主線版本的穩定性。期間遇到了很多坑,也跟著師兄學到了很多Android知識。但是人總是要擁抱變化,不能讓自己太安逸,雖然有不舍,但是我已經證明了自己的學習能力,下一步就是開始做Rom Porting了。這裡總結一下之前項目中用到最多的Fragment。
Fragment簡介Fragment可以理解成Activity中使用者介面的一個行為或者一部分,它必須被嵌套在Activity中。但是一個Fragment有它自己獨立的xml布局檔案,並且具有良好的封裝性,因此特殊情況下Fragment可以很容易用Activity來進行替換。
建立Fragment建立一個Fragment和建立Activity類似,需要實現XML布局檔案和Java Class。XML布局檔案和其他布局檔案都一樣,例如如下所示的布局檔案(fragment_layout.xml):
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/testview" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button" /></LinearLayout>
Java代碼中,一般情況下可以根據需要實現Fragment以下幾個生命週期方法:
1. onAttach():當Fragment依附於activity時被調用,可以在該方法中擷取activity控制代碼,從而實現Fragment和activity之間的通訊。2. onCreate():對Fragment做初始化。3. onCreateView():在第一次為Fragment繪製使用者介面時系統會調用此方法。4. onActivityCreated():在宿主Activity onCreate函數執行完成之後被調用,可以在這個方法裡進行Fragment自己的widget執行個體化和商務邏輯處理。5. onDestoryView():當Fragment開始被銷毀時調用。6. onStart():當Fragment可見時被調用。還有許多其他用以操縱Fragment生命週期中各個階段的回呼函數,大家可自行Google學習。
Fragment生命週期每一個Fragment都有自己的一套生命週期回調方法和處理自己的使用者輸入事件。對應的生命週期如所示:
在Activity中加入Fragment首先,需要確保Acitivity支援Fragment,因此Activity通常需要繼承自FragmentActivity。在Activity中添加Fragment通常有兩種方法:靜態和動態。靜態方法直接在Activity的XML布局檔案中加入Fragment,如下所示:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:baselineAligned="false" android:orientation="horizontal" > <fragment android:id="@+id/first" android:name="com.example.FristFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" /> <fragment android:id="@+id/second" android:name="com.example.SecondFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" /></LinearLayout>
<fragment>中的android:name 屬性指定了布局中執行個體化的fragment類當系統建立Activity布局時,它執行個體化了布局檔案中指定的每一個Fragment,並且為它們調用onCreateView()函數,以擷取每一個fragment的布局。系統直接在<fragment>元素位置插入fragment返回的view注意:每個fragment都需要一個唯一的標識,如果重啟activity,系統可用來恢複fragment(並且用來捕捉fragment的交易處理,例如移除)。為了Fragment提供ID有三種方法:
- 用android:id屬性提供一個唯一的標識
- 用android:tag屬性提供一個唯一的字串
- 如果上述兩個屬性都沒有,系統會使用其[內容] 檢視的ID
動態方法使用FragmentTranscation。可以使用FragmentTranscation的API來對Activity的Fragment進行操作(例如添加,移除,或者替換Fragment)。參考代碼如下:
FragmentManager fragmentManager = getFragmentManager()FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();ExampleFragment fragment = new ExampleFragment();fragmentTransaction.add(R.id.fragment_container, fragment);fragmentTransaction.commit();
傳入add()函數的第一個參數是Fragment被放置的ViewGroup,它由資源ID(resource ID)指定,第二個參數就是要添加的fragment。一旦通過FragmentTranscation做了更改,都應當使用commit()視變化生效。
Fragments通訊Fragments之間不應該直接進行通訊,它們之間的互動應該通過宿主Activity進行。有三種Fragment和Acitivity互動的方法:1. Activity建立帶參數的Fragment。2. Activity中保持了Fragment的物件控點,可通過控制代碼直接調用該Fragment的public方法。3. Fragment可在onAttach函數中擷取定義的listener控制代碼。建立帶參數的Fragment在某些特定的情況下,Fragment可能需要特定的參數來進行初始化。由於Fragment必須只有一個無參建構函式,因此可以考慮使用靜態newInstance方法來建立帶參數的Fragment。範例程式碼如下:
import android.os.Bundle;import android.support.v4.app.Fragment;public class TestFragment extends Fragment {public static TestFragment newInstance(int num, String title) {TestFragment fragment = new TestFragment();Bundle args = new Bundle();args.putInt("num", num);args.putString("title", title);fragment.setArguments(args);return fragment;}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);int num = getArguments().getInt("num", 0);String title = getArguments().getString("title", "");}}你可以在Activity裡,簡單的載入一個帶參數的Fragment:
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();TestFragment fragment = TestFragment.newInstance(5, "fragment title");ft.replace(R.id.placeholder, fragment);ft.commit();
調用Fragment的方法因為Activity可以擷取嵌入的Fragment的控制代碼,因此可以直接通過Fragment控制代碼調用該方法。
public class TestFragment extends Fragment {public void doSomething(String param) {// do something in fragment}}在Activity中,可以直接通過Fragment的物件控點調用該方法:
public class MainActivity extends FragmentActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TestFragment testFragment = new TestFragment(); testFragment.doSomething("some param"); }}Fragment Listener如果Fragment需要共用事件給Activity,則需要利用這個方法。Fragment中定義一個介面,並且由Activity來實現這個介面。在onAttach()方法中將實現了這個介面的Activity獲得到。在Fragment中定義介面代碼如下:
import android.support.v4.app.Fragment;public class MyListFragment extends Fragment { // ... // Define the listener of the interface type // listener is the activity itself private OnItemSelectedListener listener; // Define the events that the fragment will use to communicate public interface OnItemSelectedListener { public void onRssItemSelected(String link); } // Store the listener (activity) that will have events fired once the fragment is attached @Override public void onAttach(Activity activity) { super.onAttach(activity); if (activity instanceof OnItemSelectedListener) { listener = (OnItemSelectedListener) activity; } else { throw new ClassCastException(activity.toString() + " must implement MyListFragment.OnItemSelectedListener"); } } // Now we can fire the event when the user selects something in the fragment public void onSomeClick(View v) { listener.onRssItemSelected("some link"); }}在Activity中實現這個介面:
import android.support.v4.app.FragmentActivity;public class RssfeedActivity extends FragmentActivity implements MyListFragment.OnItemSelectedListener { DetailFragment fragment; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_rssfeed); fragment = (DetailFragment) getSupportFragmentManager() .findFragmentById(R.id.detailFragment); } // Now we can define the action to take in the activity when the fragment event fires @Override public void onRssItemSelected(String link) { if (fragment != null && fragment.isInLayout()) { fragment.setText(link); } }}
Android Fragment使用