android-如何通过接口回调来解决Fragment之间的交互

由于在android的丝线机制综fragment和acitivty会被分别实例化为两个不相干的对象,他们之间的联系由activity的一个成员对象FragmntManager来维护,Fragment实例化后到activity中的fragmentManager去注册一下,这个动作封装在Fragment对象的OnAttach中,所以你可以在fragment中声明一些回调接口,当fragment调用onAttach时,将这些回调接口实例化,这样fragment就能调用各个acivity的成员函数了,当然activity必须implements这些接口,否则会报ClassCastExceptionfragment和activity的回调机制又是OOP的又一次完美演绎!

下面通过一个例子来说明

实现的目的:将一个activity用两个fragment分割填充,左侧的fragment中有3个Button,右侧作为内容显示,当点击左侧的按钮,显示对应的文字信息。

首先是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>

效果图如下所示:

左侧的fragment布局left_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">
<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.java

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([email protected])
 * 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([email protected])
 * 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

时间: 2024-10-10 21:03:56

android-如何通过接口回调来解决Fragment之间的交互的相关文章

谈谈-Android中的接口回调技术

Android中的接口回调技术有很多应用的场景,最常见的:Activity(人机交互的端口)的UI界面中定义了Button,点击该Button时,执行某个逻辑. 下面参见上述执行的模型,讲述James对Android接口回调技术的理解(结合前人的知识和自己的实践). 使用一个比喻很形象地说明:客户端有个疑问打电话请教服务端,但服务端无法现场给出解答,相互之间约定:服务端一旦有答案,使用电话的方式反馈给客户端. 以上有三个主体:客户端.服务端和接口(方式). 接口回调的原理框图说明: Demo界面

Android中的接口回调技术

Android中的接口回调技术有很多应用的场景,最常见的:Activity(人机交互的端口)的UI界面中定义了Button,点击该Button时,执行某个逻辑. 下面参见上述执行的模型,讲述James对Android接口回调技术的理解(结合前人的知识和自己的实践). 使用一个比喻很形象地说明:客户端有个疑问打电话请教服务端,但服务端无法现场给出解答,相互之间约定:服务端一旦有答案,使用电话的方式反馈给客户端. 以上有三个主体:客户端.服务端和接口(方式). 接口回调的原理框图说明: Demo界面

Android学习笔记(十六)——碎片之间进行交互(附源码)

碎片之间进行交互 点击下载源码 很多时候,一个活动中包含一个或者多个碎片,它们彼此协作,向用户展示一个一致的UI.在这种情况下,碎片之间能进行通信并交换数据十分重要. 1.使用上一篇中创建的同一个项目,在fragment.xml中添加TextView的标识id: android:id="@+id/lblFragment1" 2.在fragment2.xml中添加一个Button,用于与fragment1进行交互: <Button android:id="@+id/btn

Android实战之接口回调

由于自己以前也困于抽象.接口等"吓人"的东西,网上又缺乏在项目中实战运用的讲解,下面我就斗胆把自己的理解和大家交流一下下. 本人也算是自学"成才",呵呵,大学时虽然学的计算机,但是对软件开发却并不感兴趣.毕业后看同学们或培训Android或培训IOS 4个月后都很快找到了不错的工作,令我感到很诧异,也很羡煞!于是我做出了人生中重要的一个决定,开始学习Android,由于本人比较穷,所以选择自学.学习的过程实为不易,从刚开始的一无所知时的苦苦挣扎,到学有所得后的应对有

Android 中的接口回调

http://blog.csdn.net/wangjinyu501/article/details/22052187 在Android中到处可见接口回调机制,尤其是UI事件处理方面.举一个最常见的例子button点击事件,button有一个点击方法onClick(),我们知道onclick()是一个回调方法,当用户点击button就执行这个方法.在源码中是这样定义的: //这个是View的一个回调接口 /** * Interface definition for a callback to be

Android ActionBar通过Tab进行不同的Fragment之间的交换

ActionBar的使用常见于4.0系统,其Tab的使用挺广泛的. 在ActionBar中添加标签(Tabs),每个标签对应的是一个Fragment,点击不同的Tab时,就会切换到对应的Fragment. 大致的步骤如下: 1.如同TabHost控件,每个tab下需要添加内容,这个内容需要结合fragment来显示,因此需创建fragment类,有几个tab就需要几个继承Fragment的类: 2.将fragment添加至ActionBar Tab上,并添加tab监听: 3.监听内部类需要实现A

Java接口回调机制

一.前言 最近在看android Fragment与Activity进行数据传递的部分,看到了接口回调的内容,今天来总结一下. 二.回调的含义和用途 1.什么是回调? 一般来说,模块之间都存在一定的调用关系,从调用方式上看,可以分为三类同步调用.异步调用和回调.同步调用是一种阻塞式调用,即在函数A的函数体里通过书写函数B的函数名来调用之,使内存中对应函数B的代码得以执行.异步调用是一种类似消息或事件的机制解决了同步阻塞的问题,例如A通知B后,他们各走各的路,互不影响,不用像同步调用那样,A通知B

Fragment与Activiy之间的交互

为了重用Fragment UI组件,我们应该把每一个fragment都构建成完全的自包含的.模块化的组件,定义他们自己的布局与行为.定义好这些模块化的Fragment后,就可以让他们关联activity,使他们与application的逻辑结合起来,实现全局的复合的UI. 通常fragment之间可能会需要交互,比如基于用户事件改变fragment的内容.所有fragment之间的交互需要通过他们关联的activity,两个fragment之间不应该直接交互. 定义一个接口 为了让fragmen

Android实战之 万能的接口回调

转载请标明原地址:http://blog.csdn.net/gaolei1201/article/details/47084111 前言:本人也算是自学"成才",呵呵,大学时尽管学的计算机,可是对软件开发却并不感兴趣. 毕业后看同学们或培训Android或培训IOS 4个月后都非常快找到了不错的工作.令我感到非常诧异,也非常羡慕!于是我做出了人生中重要的一个决定.開始学习Android.因为本人比較穷,所以选择自学. 学习的过程实为不易,从刚開始的一无所知时的苦苦挣扎,到学有所得后的应