您的位置:首页 > 移动开发 > Android开发

浅析 android 接口回调机制

2015-09-01 15:39 639 查看
一 接口回调机制在android中的应用十分广泛,比如button的点击事件,就用到的是接口回调,下面的代码为android中view的click方法:

/**
     * view 的click事件
     * Interface definition for a callback to be invoked when a view is clicked.
     */
    public interface OnClickListener {
        /**
         * Called when a view has been clicked.
         *
         * @param v The view that was clicked.
         */
        void onClick(View v);
    }


二 下面通过一个小程序,来了解下接口回调。

1.首先我们在这里创建了一个项目,InterfaceCallback,项目的目录结构如下:




2 首先,我们来讲解主界面的布局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="vertical">

    <TextView
        android:gravity="center"
        android:id="@+id/avtivity_title"
        android:layout_width="match_parent"
        android:layout_height="70dp"
        android:layout_centerInParent="true"
        android:text="activity_title_before(更换前)"
        android:textSize="18sp" />

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#ff0000"></View>

    <fragment
        android:id="@+id/fragment"
        android:name="com.example.admin.interfacecallback.fragment.MyFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginTop="3dp"
        android:layout_weight="1"
        tools:layout="@layout/my_fragment_layout"></fragment>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/reset_fragment_text"
            android:layout_width="0dp"
            android:layout_height="65dp"
            android:layout_weight="1"
            android:text="重置Fragment标题"
            android:textSize="13sp" />

        <Button
            android:id="@+id/change_fragment_text"
            android:layout_width="0dp"
            android:layout_height="65dp"
            android:layout_weight="1"
            android:text="切换Fragment标题"
            android:textSize="13sp" />
    </LinearLayout>

</LinearLayout>


如上,我们的主布局为Linearlayout,布局方式为垂直,在布局中有一个TextView为activity标题一个fragment标签,底部有两个按钮,分别为重置
Fragment标题和切换Fragment标题,(注:在这里我们仅仅只是想说明接口回调模式,其中的变化有很多种,有兴趣的朋友可以多多尝试)fragment
标签则表示的是Fragment的布局。其中引用fragment的布my_fragment_layout.xml如下:


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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/fragment_title"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:gravity="center"
        android:text="fragment_title_before(更换前)"
        android:textSize="18sp" />

    <LinearLayout
        android:layout_centerInParent="true"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <Button
            android:layout_weight="1"
            android:textSize="16sp"
            android:text="重置activity标题"
            android:id="@+id/reset_activity_title"
            android:layout_width="0dp"
            android:layout_height="60dp" />

        <Button
            android:layout_weight="1"
            android:textSize="16sp"
            android:text="切换activity标题"
            android:id="@+id/change_activity_title"
            android:layout_width="0dp"
            android:layout_height="60dp" />
    </LinearLayout>

</RelativeLayout>


我们可以看到在Fragment中的布局也是相对简单的,也是有一个TextView显示fragment标题两个Button用于切换和重置activity的标题。下面我们就通过详细的代码来讲解怎么实现接口回调.

3.下面我们来看看ActivityCallback接口,用于改变Fragment中标题的接口,代码如下:


package com.example.admin.interfacecallback.callback;

/**
 * Created by admin on 2015/9/1.
 */
public interface ActivityCallback {

    /**
     * 这里用于改变fragment中的title,需要传入一个参数
     * @param title 更改后的title名称
     */
    void changeFragmentTitle(String title);

    /**
     * 重置Fragment标题
     */
    void resetFragmentTitle(String title);
}


如上,这个方法在更改的时候需要传入一个参数为,你想要更改为的title名称。

4.再来看看FragmentCallback中的代码,同样只有一个方法,传入一个更改后的title名称即可,不说废话,看代码:


package com.example.admin.interfacecallback.callback;

/**
 * Created by admin on 2015/9/1.
 */
public interface FragmentCallback {

    /**
     * 更改Activity中的title名称
     * @param title 更改后的标题名称
     */
    void changeActivityTitle(String title);

    /**
     * 重置Activity的标题
     * @param title
     */
    void resetActivityTitle(String title);

}


5.下面我们看看MyFragment中的代码,在代码中描述已经说的很清晰了,这里我也就不再解释,上代码:


package com.example.admin.interfacecallback.fragment;

import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

import com.example.admin.interfacecallback.R;
import com.example.admin.interfacecallback.callback.ActivityCallback;
import com.example.admin.interfacecallback.callback.FragmentCallback;

/**
 * Created by admin on 2015/9/1.
 */
public class MyFragment extends Fragment implements ActivityCallback{

    /**
     * 定义fragment的根布局View,用于初始化控件
     */
    private View view;
    /**
     * Fragment的标题
     */
    private TextView fragment_title;
    /**
     * 更改activity标题的按钮
     */
    private Button change_activity_title,reset_activity_title;
    /**
     * activity中的点击回调
     */
    private FragmentCallback callback;
    /**
     * 更换后的activity标题名称
     */
    private String change_after_title = "change_title_after(更换后)";
    /**
     * 更换后的activity标题名称
     */
    private String change_before_title = "change_title_before(更换前)";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        /**
         * 初始化回调接口
         * 1.因为activity已经实现了FragmentCallback,所以他已经为FragmentCallback的子类,因此在这可以直接强转
         */
        callback = (FragmentCallback) getActivity();
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        view = inflater.inflate(R.layout.my_fragment_layout,container,false);
        /**
         * 初始化界面
         */
        init();
        return view;
    }

    private void init() {

        fragment_title = (TextView) view.findViewById(R.id.fragment_title);
        change_activity_title = (Button) view.findViewById(R.id.change_activity_title);
        change_activity_title.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /**
                 * 判断非空
                 */
                if (callback != null)
                {
                    callback.changeActivityTitle(change_after_title);
                }

            }
        });
        reset_activity_title = (Button) view.findViewById(R.id.reset_activity_title);
        reset_activity_title.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /**
                 * 判断非空
                 */
                if (callback != null)
                {
                    callback.changeActivityTitle(change_before_title);
                }
            }
        });
    }

    /**
     * 当点击Activity中的切换按钮时的回调
     * @param title 更改后的title名称
     */
    @Override
    public void changeFragmentTitle(String title) {

        if (!TextUtils.isEmpty(title))
        {
            fragment_title.setText(title);
        }

    }

    /**
     * 用于还原最初的状态
     * @param title
     */
    @Override
    public void resetFragmentTitle(String title) {

        if (!TextUtils.isEmpty(title))
        {
            fragment_title.setText(title);
        }

    }
}


6.MainActivity中的代码,如下:


package com.example.admin.interfacecallback;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.example.admin.interfacecallback.callback.FragmentCallback;
import com.example.admin.interfacecallback.fragment.MyFragment;

public class MainActivity extends AppCompatActivity implements FragmentCallback{

    /**
     * activity的标题栏
     */
    private TextView avtivity_title;
    /**
     * 界面引用fragment的实例
     */
    private MyFragment fragment;
    /**
     * 更换fragment的标题title按钮
     */
    private Button change_fragment_text,reset_fragment_text;
    /**
     * 更改过后的fragment标题名称
     */
    private String change_after_title = "fragment_title_after(更换后)";

    /**
     * 更改过后的fragment标题名称
     */
    private String change_before_title = "fragment_title_before(更换前)";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        /**
         * 初始化界面控件
         */
        initView();

    }

    private void initView()
    {

        avtivity_title = (TextView) findViewById(R.id.avtivity_title);
        change_fragment_text = (Button) findViewById(R.id.change_fragment_text);
        fragment = (MyFragment) this.getFragmentManager().findFragmentById(R.id.fragment);
        change_fragment_text.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /**
                 * 判断非空
                 */
                if (fragment != null)
                {
                    /**
                     * 因为MyFragment已经实现了ActivityCallback接口,所以这里可以直接使用
                     */
                    fragment.changeFragmentTitle(change_after_title);
                }
            }
        });
        reset_fragment_text = (Button) findViewById(R.id.reset_fragment_text);
        reset_fragment_text.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /**
                 * 判断非空
                 */
                if (fragment != null)
                {
                    /**
                     * 因为MyFragment已经实现了ActivityCallback接口,所以这里可以直接使用
                     */
                    fragment.changeFragmentTitle(change_before_title);
                }
            }
        });

    }

    /**
     * 当点击Fragment中的切换按钮时的回调
     * @param title 更改后的标题名称
     */
    @Override
    public void changeActivityTitle(String title) {

        if(!TextUtils.isEmpty(title))
        {
            avtivity_title.setText(title);
        }

    }

    /**
     * 重置activity的title信息
     * @param title
     */
    @Override
    public void resetActivityTitle(String title) {
        if(!TextUtils.isEmpty(title))
        {
            avtivity_title.setText(title);
        }
    }
}


7.在这里我们主要核心,在于如下几句代码,
    1.在MainActivty中获得MyFragment实例(这里我使用的是app包下的Fragment,若是你使用的是V4包下的Fragment那么你就需要让MainActivity实现FragmentActivity),以及将要更换的意图交给MyFragment类响应.


/**
     * 界面引用fragment的实例
     */
    private MyFragment fragment;
    fragment = (MyFragment) this.getFragmentManager().findFragmentById(R.id.fragment);

/**
     * 判断非空
     */
    if (fragment != null)
    {
       /**
         * 因为MyFragment已经实现了ActivityCallback接口,所以这里可以直接使用
         */
          fragment.changeFragmentTitle(change_after_title);
    }

    /**
     * 判断非空
      */
       if (fragment != null)
       {
       /**
        * 因为MyFragment已经实现了ActivityCallback接口,所以这里可以直接使用
        */
          fragment.changeFragmentTitle(change_before_title);
        }

        2.在MyFragment中的onCreate方法中获取FragmentCallback对象(因为在这里MainActivity已经实现了FragmentCallback接口,所以该类已经为该接口子类,所以我在这里直接使用强转,若是你不明白,也可以在这里将声明的变量类型更换为MainActivity然后调用对应的接口方法也可以)。

    /**
     * activity中的点击回调
     * 这里这个对象的类型可以声明成如下形式
     * MainActicity callback
     */
    private FragmentCallback callback;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        /**
         * 初始化回调接口
         * 1.因为activity已经实现了FragmentCallback,所以他已经为FragmentCallback的子类,因此在这可以直接强转
         * 2.当上面的变量类型声明为Mainactivity时,下面这句话可变为
         * callback = (MainActivity)getActivity();
         */
        callback = (FragmentCallback) getActivity();
    }
    多余的不在这里讲了,下面给大家看看最终的效果。


8.最终的效果演示如下:




9.到这里简单的就讲完了。其实也是很简单的,只要大家多多尝试,就会有很多比较细小的发现。


源码下载

链接为: http://download.csdn.net/detail/hxy_blog/9071151

欢迎大家纠正错误,如有问题可进行评论,谢谢。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: