android-如何經過接口回調來解決Fragment之間的交互

  因爲在android的絲線機制綜fragment和acitivty會被分別實例化爲兩個不相干的對象,他們之間的聯繫由activity的一個成員對象FragmntManager來維護,Fragment實例化後到activity中的fragmentManager去註冊一下,這個動做封裝在Fragment對象的OnAttach中,因此你能夠在fragment中聲明一些回調接口,當fragment調用onAttach時,將這些回調接口實例化,這樣fragment就能調用各個acivity的成員函數了,固然activity必須implements這些接口,不然會報ClassCastExceptionfragment和activity的回調機制又是OOP的又一次完美演繹!html

下面經過一個例子來講明java

實現的目的:將一個activity用兩個fragment分割填充,左側的fragment中有3個Button,右側做爲內容顯示,當點擊左側的按鈕,顯示對應的文字信息。
android

首先是activity_main.xml的佈局文件併發

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    tools:context=".MainActivity">
    <FrameLayout
        android:id="@+id/ui_container"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1">
    </FrameLayout>
    <FrameLayout
        android:id="@+id/details_container"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="@android:color/holo_blue_light">
    </FrameLayout>
</LinearLayout>

效果圖以下所示:app

左側的fragment佈局left_fragment.xml以下所示:
ide

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
<Button
    android:id="@+id/firstButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/first_button"/>
<Button
    android:id="@+id/secondButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/second_button"/>
<Button
    android:id="@+id/thenButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/then_button"/>
</LinearLayout>

效果圖以下所示:函數

右側的fragment佈局right_fragment.xml以下:佈局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
<TextView
    android:id="@+id/content"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
</LinearLayout>


上面的佈局文件都很簡單,沒有什麼好說的,下面 ,我將對java文件的代碼進行相應的解釋:學習

先將LeftFragment.javaui

package learn.dreamcoder.com.learn;

import android.app.Activity;
import android.app.Fragment;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

/**
 * Description:
 * User: Dream_Coder(chenchen_839@126.com)
 * Date: 2015-07-29
 * Time: 15:15
 */
public class LeftFragment extends Fragment{
    public interface MyListener{
        public void showMessage(int index);
    }
    private MyListener mListener;
    private Button mButton1;
    private Button mButton2;
    private Button mButton3;
    public Button lastButton;

    @Override
    public void onAttach(Activity activity) {/*判斷宿主activity是否實現了接口MyListener*/
        super.onAttach(activity);
        try {
            mListener = (MyListener) activity;
        }catch (ClassCastException e) {
            throw new ClassCastException(getActivity().getClass().getName()
                    +" must implements interface MyListener");
        }
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.left_fragment,container,false);
        return view;
    }

    @Override
    public void onResume() {
        super.onResume();
        mButton1 = (Button) getActivity().findViewById(R.id.firstButton);
        mButton2 = (Button) getActivity().findViewById(R.id.secondButton);
        mButton3 = (Button) getActivity().findViewById(R.id.thenButton);
        mButton1.setOnClickListener(new MyButtonClickListener());
        mButton2.setOnClickListener(new MyButtonClickListener());
        mButton3.setOnClickListener(new MyButtonClickListener());
    }
    class MyButtonClickListener implements View.OnClickListener{

        @Override
        public void onClick(View v) {
            Button button = (Button) v;
            if(lastButton != null) {
                lastButton.setBackgroundColor(0);
            }
            button.setBackgroundColor(Color.parseColor("#00FF00"));
            lastButton= button;
            if(button == mButton1) {
                mListener.showMessage(1);
            }
            if(button == mButton2) {
                mListener.showMessage(2);
            }
            if(button == mButton3) {
                mListener.showMessage(3);
            }
        }
    }
}

該文件中的MyListener是這個交互過程的關鍵,將這個接口暴露出去,交於宿主activity來實現,而宿主activity實現該接口,根據傳入的參數,作出對於的操做,併發出適當的命令交付給第二個Fragment,從而能夠改變第二個fragment中的組件狀態。


整個過程能夠理解爲:Fragement1  ----》    activity   -----》   Fragment2

Fragment之間通常是不會直接進行交互的,而是須要經過宿主activity做爲橋樑來進行通話。

宿主activity負責Fragement之間的業務通話,而Fragment僅僅負責維護本身的組件狀態就能夠了,須要業務操做的部分暴露出去,交給宿主來作,這個暴露過程就是經過接口的方式。


例如在上述代碼中,類MyButtonClickListener中須要執行mListener.showMessage()函數來在Fragment2中展現信息,可是在該Fragment中並無任何語句來對該接口進行實現,而是直接使用,由於咱們的目的就是不直接與Fragment2進行交互,可是咱們能夠把這個接口交付給宿主activity,讓它來實現,讓它來操做這一切,因而乎,對於LeftFragment來說就不用擔憂這個問題,直接使用就行了,由於宿主已經解決了這一切。

下面講解MainActivity.java代碼:

package learn.dreamcoder.com.learn;

import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity implements LeftFragment.MyListener{
    private TextView showMessageView;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        FragmentManager manager = getFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        transaction.add(R.id.ui_container,new LeftFragment());
        transaction.add(R.id.details_container,new RightFragment());
        transaction.commit();
    }

    @Override
    public void showMessage(int index) {
        if(1 == index) {
            showMessageView.setText(R.string.first_page);
        }else if(2 == index) {
            showMessageView.setText(R.string.second_page);
        }else {
            showMessageView.setText(R.string.then_page);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        showMessageView = (TextView) findViewById(R.id.content);
    }
}


在宿主activity中首先要作的事情就是要實現剛纔的接口,這個接口的目的就是要根據剛纔暴露出來是時候傳入的參數來向RightFragment發出命令,改變它的內容。因此要獲得RightFragment中顯示的TextView 的引用,而後設置文字便可了。這就很好理解了

下面是RightFragment.java

package learn.dreamcoder.com.learn;

import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * Description:
 * User: Dream_Coder(chenchen_839@126.com)
 * Date: 2015-07-29
 * Time: 15:16
 */
public class RightFragment extends Fragment{
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.right_fragment,container,false);
    }
}

這個很簡單,沒有什麼好說的,相信大家都能看明白。就不講解了。

總結一下,對於兩個Fragment之間的交互過程,若是想向Fragment發出什麼請求,直接把這個請求封裝成一個接口,暴露出去,交由宿主來實現就行了。


本人只是爲了學習和理解,感受這個代碼仍是頗有意義的,可是沒有太多的講解,我根據本身的理解寫了一些註解。

在這裏對原做者表示感謝

該文的原地址:http://www.360doc.com/content/14/0519/10/17121610_378958268.shtml

相關文章
相關標籤/搜索