Activity、Fragment、Service间的通信

小小的总结一下Activity、Fragment、Service之间的通信方式:

一、Activity与Activity通信

1、intent(这个相信大家都用过,就不做过多解释了);
2、通过类的静态成员变量,类的静态成员变量可以通过类名访问;
3、通过全局变量进行通信;
4、第三种方式,可以借助内存外的工具进行通信:
    3-1、使用Sqlite数据库;
    3-2、SharePreference;
    3-3、文件存储;
5、开启service,但开销较大,且service随时会挂掉,维护起来成本较大

二、Activity与Fragment之间的通信

1、使用接口:

activity向fragment中传递数据:
界面由activity跳转到fragment时,在activity中通过setArguments()方法保存Bundle数据,然后在fragment中通过
getArguments()方法获取Bundle数据。
activity中:

public class Main2Activity extends AppCompatActivity {

            Button button = null;
            EditText et = null;
            MyFragment1 myFragment1 = null;

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

                button = findViewById(R.id.btn_activity2);
                et = findViewById(R.id.et_activity2);

                button.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        String dataACMain2  = et.getText().toString();
                        Bundle bundle = new Bundle();
                        if(myFragment1==null ) {
                            myFragment1 = new MyFragment1();
                        }
                        bundle.putString("dataACMain2", dataACMain2);
                        myFragment1.setArguments(bundle);
                        FragmentTransaction transaction =   getSupportFragmentManager().beginTransaction();
                        transaction.replace(R.id.activity_main2, myFragment1);
                        transaction.commit();
                    }
                });
            }
        }
**fragment中:**
    String data = getArguments().getString("dataACMain2");
        tvFragment.setText(data);

fragment向activity中传递数据:
同样的一段代码:
主要原理是: 在fragment中定义一个接口并声明,然后调用接口方法传入要传给activity的数据,到activity中,activity需要实现这个接口,在接口方法中获取传过来的data;需要注意的是,在fragment中获取接口“实例”的时候是在onAttach()方法中,主要代码如下:
fragment中:

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        myCallBack = (MyCallBack) getActivity();

    }


    public interface MyCallBack {
        void sendData(String data);
    }

activity中:

public class MainActivity extends AppCompatActivity implements MyFragment1.MyCallBack{

    TextView tv_show = null;
    EditText input = null;
    Button button = null;


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

        tv_show = findViewById(R.id.tv_show);
        input = findViewById(R.id.et_ac_main);
        button = findViewById(R.id.btn_main_send_data);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(MainActivity.this, Main2Activity.class));
                /*String data = input.getText().toString();
                Bundle bundle = new Bundle();
                bundle.putString("data", data);
                Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.myFragment1);
                fragment.setArguments(bundle);*/
            }
        });
    }

    @Override
    public void sendData(String data) {
        tv_show.setText(data);
    }
}

2、使用Handler

activity向fragment传值:
接受消息的handler肯定是写在fragment中,然后在handleMessage()方法中更新UI,所以发送消息就应该写在activity中了,在这声明一个handler, 然后再点击事件中调用handler.sendMessage()方法,看起来似乎Ok了,那么如何保证activity中的handler和fragment中的handler是一个hanlder呢,可以在activity中定义一个setHandler方法,传入一个hander赋给activity的handler,然后可以在fragment的onAttach()方法中获取activity实例,再调用setHandler()方法即可,代码如下:

public class MainActivity extends AppCompatActivity {

Handler mHandler;

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

    Button sendData = findViewById(R.id.btn_ac);
    final EditText data = findViewById(R.id.et_ac);
    sendData.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            String s = data.getText().toString();
            Bundle bundle = new Bundle();
            bundle.putString("data", s);
            Message msg = Message.obtain();
            msg.setData(bundle);
            mHandler.sendMessage(msg);
        }
    });
}

public void setHandler(Handler handler) {
    this.mHandler = handler;
}

}

public class Fragment1 extends Fragment {
MainActivity mActivity;
TextView tv;

Handler mHandler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        tv.setText(msg.getData().getString("data"));
    }
};

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

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    mActivity = (MainActivity) getActivity();
    mActivity.setHandler(mHandler);
}

反过来试试,fragment向activity
同理,不过这次是在activity中创建一个handler,然后在fragment中定义一个setHandler()方法,在activity中获取fragment实例,用getSupportManager().findFragmentById()就行,然后后面的一样;

3、使用广播,这个太简单了,你们自己写

4、通过EventBus

activity向fragment发送信息:
1、定义一个MessageEvent类;
public class MessageEvent {

    private String message;

    public MessageEvent(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

2、activity中
发送MessageEvent事件

        sendData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                EventBus.getDefault().post(new MessageEvent(data.getText().toString()));
            }
        });

3、fragment中
首先需要注册订阅者:
EventBus.getDefault().register(this);
然后写一个接收MessegeEvent的事件(方法名任意写,只需要加上订阅注解就行)

@Subscribe
public void onMoonEvent(MessageEvent messageEvent) {
   tv.setText(messageEvent.getMessage());
}

就是这么简单!!

三、activity与Service通信

我的天,我真的不想再多说啥了,在activity中一直报service空指针,原来是忘了在manifest中定义。。
好了,开始正文:
模拟一个使用service进行下载的进度条,首先定义一个service:

public class MyService extends Service{

   public static final int MAX_PROGRESS = 100;
    private int progress = 0;

    public int getProgress() {
        return progress;
    }

    public void startDownload() {
        new Thread() {
            @Override
            public void run() {
                super.run();
                while (progress<MAX_PROGRESS) {
                    progress +=5;
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new MyBinder();
    }

    public class MyBinder extends Binder {

        public MyService getService() {
            return MyService.this;
        }
    }
}

然后是activity中;

ServiceConnection connection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        //获取service实例
        myService = ((MyService.MyBinder)service).getService();
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {

    }
};
    //更新进度条
    public void onProgress() {
    new Thread() {
        @Override
        public void run() {
            super.run();
            while (progress<MyService.MAX_PROGRESS) {
                progress = myService.getProgress();
                bar.setProgress(progress);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }.start();
}

    Intent intent = new Intent(this, MyService.class);
    bindService(intent, connection, BIND_AUTO_CREATE);
    sendData.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //EventBus.getDefault().post(new MessageEvent(data.getText().toString()));
            //开始下载
            myService.startDownload();
            //可视化监听下载进度
            onProgress();
        }
    });

然后其实更新ui的方式使用接口的方式更好,可以试一下。
在service中定义接口并定义传递接口的方法:

public void setOnProgressListener(OnProgressListener onProgressListener) {
    this.mOnProgressListener = onProgressListener;
}

public interface OnProgressListener{
    void onProgressChange(int progress);
}

然后传入要改变的数据:

public void startDownload() {
    new Thread() {
        @Override
        public void run() {
            super.run();
            while (progress<MAX_PROGRESS) {
                progress +=5;
                mOnProgressListener.onProgressChange(progress);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }.start();
}

activity中:
实现接口

myService.setOnProgressListener(new MyService.OnProgressListener() {
      @Override
      public void onProgressChange(int progress) {
          onProgress(progress);
      }
  });

更新ui的方法:

public void onProgress(final int progress1) {
    new Thread() {
        @Override
        public void run() {
            super.run();
            while (progress1 < MyService.MAX_PROGRESS) {
                bar.setProgress(progress1);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }.start();
}

这样更好一点;
当然可以用广播,比较简单,你们自己实现以下,这里就不贴代码了。。

四、fragment与fragment通信

1、通过接口回调的方式:

    fragment和fragment之间不能直接通信,必须通过依赖的activity进行中转后才可通信:
        通过接口:
        步骤:1、在发送方定义接口(要发送数据的fragment);
             2、在接受方实现接口(acitivity实现接口,获取数据,在实现的方法中调用另外一个fragment的公共方法);
             3、传入数据;
        例子中左边fragment向右边fragment发送数据:
        代码如下:


```
public class LeftFragment extends Fragment {

    EditText etFmLeft;
    Button btnFmLeft;
    DataListener dataListener;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_left, container, false);
        etFmLeft = view.findViewById(R.id.et_fm_left);
        btnFmLeft  =view.findViewById(R.id.btn_fm_left);
        return view;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        btnFmLeft.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String data = etFmLeft.getText().toString();
                dataListener.showData(data);
            }
        });
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        dataListener = (DataListener) getActivity();
    }

    public interface DataListener{
        void showData(String data);
    }
}

public class MainActivity extends AppCompatActivity implements LeftFragment.DataListener{

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

        rightFragment= (RightFragment)getSupportFragmentManager().findFragmentById(R.id.fragment_right);
    }

    @Override
    public void showData(String data) {
        rightFragment.showData(data);
    }
}


public class RightFragment extends Fragment {

    TextView tvShow;
    LeftFragment.DataListener listener;

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

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        listener = (LeftFragment.DataListener) getActivity();
    }

    public void showData(String data) {
        tvShow.setText(data);
    }
}

“`

2、通过广播:
同一个例子:
LeftFragment
String data = etFmLeft.getText().toString();
Intent intent = new Intent(“data”);
intent.putExtra(“data”, data);
LocalBroadcastManager.getInstance(getActivity()).sendBroadcast(intent);

RightFragment
mLBM = LocalBroadcastManager.getInstance(getActivity());
IntentFilter filter = new IntentFilter(“data”);
mLBM.registerReceiver(receiver, filter);
}

BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String data = intent.getStringExtra("data");
        tvShow.setText(data);
    }
};

3、通过Handler
参照activity和fragment通信可以做出来;

4、通过EventBus
和activity与fragment通信完全一样,可自行实现。

参考文章:
(http://blog.csdn.net/as4399/article/details/54799103)
EventBus的使用
(http://blog.csdn.net/u012702547/article/details/49786417)
activity与service间通信

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值