Android进阶之路 - 那些年我被接口回调绕晕了

当思维逻辑有限之时总会因为简单至极的东西而踌躇不安,关于接口回调这种简单的思想,我也曾辗转反侧,导致每个阶段的想法不尽相同,所以此篇记录了我不同时期对其意义的理解,当年每个时期得理解也分别写了一片blog,但是现在我都综合在了一起 ~

早期思考
当年我被接口回调绕晕的时候,后来回头一看发现这其实就是一个简单的代理方法,对大家帮助不大,因为是回忆,所以不做什么大修改了,说到这里大家可以关闭了 ,加油 ~

简单结构图:
Android进阶之路 - 那些年我被接口回调绕晕了_第1张图片
MainActivity

package com.example.call_back_demo;

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

public class MainActivity extends Activity implements OnClickListener, CallBack {
	private TextView mBtn;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		mBtn = (TextView) findViewById(R.id.btn);
		
		/**
		 * 回调的思想:
		 * 回调的描述莫过于说:"我现在办不了这这件事情,等我能办了,我就告诉你."
		 * 
		 * 回调步骤:
		 * 1.首先回调是涉及到接口
		 * 2.数据的处理方式
		 * 3.需要的地方告诉其处理的结果
		 * */
		mBtn.setOnClickListener(this);
	}
	
	//点击事件,创建办事儿着,由他通过接口告诉我们处理的结果
	@Override
	public void onClick(View v) {
		DataSpeace data=new DataSpeace(this);
		data.setData(this);
	}
	
	//实现了我们定义的接口
	public void Basket(Object obj) {
			Toast.makeText(this, "obj="+obj, 0).show();
	}

	/**
	 * 2.篮子已有,那么我们创建一个类来存放之前我们办事儿的"控件"
	 * */
	public class DataSpeace{
		//接口充当成员
		//创建成员变量和成员方法,且做初始化
		public CallBack mCallBack;
		public DataSpeace(CallBack mCallBack) {
			this.mCallBack = mCallBack;
		}
		//存放数据的方式了,处理方案写在这里
		public void setData(CallBack obj){
			Toast.makeText(MainActivity.this, "我可以处理这件事儿了="+obj, 0).show();
		}
	}
}

接口必不可少:

package com.example.call_back_demo;

/**
 * 1.接口(篮子,数据后续存放的控件)
 * */
public interface CallBack {
	void Basket(Object obj);
}

如果想运行Demo,布局当然必不可少:

<RelativeLayout 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:background="#fff"
     >

    <TextView
        android:background="#658742"
        android:layout_centerInParent="true"
        android:id="@+id/btn"
        android:textColor="#fff"
        android:padding="5dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="回调Demo" />
RelativeLayout>

中期思考

接口回调在Android中用的太多,当你学不精的时候,会发现有很多种方式回调,希望以下的对你有所帮助

效果图:
这里写图片描述

接口:

package com.example.myapplicationdelect;

public interface Ditch {
    //用于交流,获取答案----好比一个渠道
    void talk(String string);
}

Student :

package com.example.myapplicationdelect;


import android.util.Log;

public class Student implements Ditch{
    Teacher teacher;

    public Student(Teacher teacher){
        this.teacher=teacher;
    }

    //这里是问的问题,这里调用Teacher的方法
    public void ask(String ask){
        teacher.answer(Student.this,ask);
    }

       @Override
    public void talk(String string) {
        Log.e("tag","This is Te }

Teacher

package com.example.myapplicationdelect;

public class Teacher {
   public void  answer(Ditch ditch,String ask){
            ditch.talk("这其实是一个简单的逻辑处理,我们在Student中进行Teacher的引用,同时也引用他的方法,只不过我们在Student中同时做了回调的监听,当Teacher做完任务的时候会直接返回给我们需要的数据");
    }
}

MainActivity

package com.example.myapplicationdelect;

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


public class MainActivity extends AppCompatActivity  {

        public TextView mText;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mText=(TextView)   findViewById(R.id.main);


        mText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //这里我们看到了,我们在Student中持有Teacher的引用
                Teacher teacher = new Teacher();

                Student student = new Student(teacher);

                student.ask("这就是我们要问的问题,这里用于接收回调");

            }
        });
    }
}

后期思考

对…,你没有看错!接口回调这已经是我写的第三篇博文了,之前的概念一直迷迷糊糊,一直照猫画虎,只有其形,而无其意,这篇本章可能是目前为止理解最深的一篇关于接口回调的博文了,我以俩种方式进行讲解的,第一种是常规方式,进行举例,第二种方式是已观察者和订阅者的理解举例的。

后面的补充内容,为后期补录的彩蛋!

Effect :
Android进阶之路 - 那些年我被接口回调绕晕了_第2张图片

代码中的 A/B/C标注均有作用,后续可自行查看执行逻辑。

个人理解:
1.接口回调主要有三方,一方为需求方(A方),这里我们往往要获取我们想要的数据,如我们需要投资理财产品,这时候我们就需要找对应平台产品去投资,就像房屋中介一样的性质,这里我们用的就是接口(一个容器,简称B方),由B去帮我们找数据,找资源,让他去处理,而B去查看的区域,就是C方了, 这里告诉了我们该具体都是哪一款产品,哪一款房子!(其实在这里我们已经把我们想要的数据存储在了B方),之后我们就可以返回A方,进行数据填充,确定投资方向!

这里的执行逻辑是 :A - B - C - A
这里的写入(就是写代码的顺序)逻辑是:B - C - A or B - A -C

2.现在的三方框架如EvEntBus或者RxAndroid or RxJava,EventBus下我们在数据改变处(监听)可以发送状态,进行数据存入,然后在数据可需处,进行EventBus的注册,注册, 然后通过sub方法进行数据读取进行操作。
这个更像Rx下的机制,我们都知道现在很多这样的开发模式中,有观察者,被观察者,执行者,其实这里也可以很好的诠释接口回调的问题,我们在数据获取的类,放入被观察者(接口),然后回到数据可需处,等被观察者的数据的存入,我们在当前调用执行者进行逻辑处理

OwnListener (接口 - 容器)

package com.yl.aninterface.interfacedata;

/**
 * Created by YongLiu on 2017/7/21.
 */
public interface OwnListener {
     void setData (String string);
}

Listener (监听处 - 相当于Set数据的过程)

package com.yl.aninterface.interfacedata;

import android.content.Context;

/**
 * Created by YongLiu on 2017/7/21.
 */

public class Listener {
    public Context mContext;
    public OwnListener ownListener;

    public Listener(Context context,OwnListener listener){
        this.mContext=context;
        this.ownListener=listener;

    }
    
    //B :数据处理
     void setListener(){
        ownListener.setData("这里我们储存了数据");
    }
}

MainActivity (这里我们相当于发送请求(执行过程:1.发送 2.查看接口实现处 3.接口实现处获取的数据 4.设置接口中已经保存的数据)):

package com.yl.aninterface.interfacedata;

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

public class MainActivity extends AppCompatActivity implements View.OnClickListener,OwnListener {

    private TextView mView;
    private TextView mContent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mView = (TextView) findViewById(R.id.tv_btn);
        mContent = (TextView) findViewById(R.id.tv_content);
        mView.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        // A :相当于发送数据
        if(v.getId()==R.id.tv_btn){
             new Listener(this, this).setListener();
        }
    }

    // C :获取数据
    @Override
    public void setData(String string) {
        mContent.setText(string);
    }
}

补充内容:因为准备在新项目中采用MVP的开发模式进行开发,所以接口回调的使用必须熟练使用,故意进行博文补录

目前梳理之后,我归结为接口的回调的常用使用方式有三种,下面通过代码片段帮助大家理解

第一种,常规监听

思想总结 : A类调用B类方法,当B类的方法回调接口,把结果传回A类

下面代码中,MainActivity 代表 A类, AClass代表B类

执行步骤:

1.创建一个接口,同时接口内部创建一个方法,用于数据回传(MainActivity 处实现此接口),如

package com.bakheet.effect.interfacedemo;

/**
 * Created by YongLiu on 2017/11/8.
 */

public interface MainListener {
    void setData(String data);
}

2.在ManiActivity中实现这个接口,如

    @Override
    public void setData(String data) {
        mBtn.setText(data);
	}
       

3.调用AClass的方法,首先要拥有AClass的实例,之后调取AClass中的

  aClass = new AClass(this);
         mBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                aClass.setData("MainActivity 传到 AClass的数据");
            }
        });

4.AClass类的代码要注意,首先要拥有MainListener的成员变量,注册在成员方法中,如

    public MainListener listener;

    public AClass(MainListener listener){
        this.listener=listener;
    }

    public void setData(String data) {
        String ste=data+"AClass 接收信息之后的回传";
        listener.setData(ste);
    }

第二种方法,常用的成功,失败回调

1.创建接口

package com.bakheet.effect.interfacedemo;

/**
 * Created by YongLiu on 2017/11/8.
 */

public interface BListener {
    void Succeed();
    void Faieail();
}

2.AClass类创建方法,满足一定条件之后,使用接口进行标记

  void setListener(String ste,BListener bListener){
        if(ste.equals("MainActivity 传到 AClass的数据AClass 接收信息之后的回传")){
            Log.e("tag","AClass要传入的数据");
            bListener.Succeed();
        }else{
            Log.e("tag","Main传来的数据");
            bListener.Faieail();
        }
    }

3.MainActivity 调用处

   aClass = new AClass(this);

   aClass.setListener(mBtn.getText().toString(), new BListener() {
            @Override
            public void Succeed() {
                Log.e("tag", "Set Succeed回调");
            }

            @Override
            public void Faieail() {
                Log.e("tag", "Set Faieail回调");
            }
        });

第三种方式 ,Activity 之间接口回调

主要思想 :中转站思想,使用Manager进行接口中转,如

package com.bakheet.effect.interfacedemo;

/**
 * Created by YongLiu on 2017/11/8.
 */

public class InterManager {
    public SecoundListener secoundListener;
    private InterManager() {
    }

    public static InterManager interManager = new InterManager();

    public InterManager getInstance() {
        return interManager;
    }

    public void setSecoundListener(SecoundListener secoundListener) {
        this.secoundListener = secoundListener;
    }
}

SecoundListener

package com.bakheet.effect.interfacedemo;

public interface SecoundListener{
        void getData(String data);
    }

MainActivity

	//注册监听  同时实现接口内方法
 InterManager.interManager.setSecoundListener(this);

    @Override
    public void getData(String data) {
        Toast.makeText(this, "---" + data, Toast.LENGTH_SHORT).show();
        mBtn.setText(data);
    }

SecoundActivity

     mBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                sendData(InterManager.interManager.secoundListener);
            }
        });

   private void sendData(SecoundListener listener) {
        listener.getData("回头已是百年时");
    }

下载地址

你可能感兴趣的:(#,必备初级知识点)