1. overview
In previous blog posts, I briefly introduced how to achieve information exchange between fragment s: ___________<Interaction between Fragment and Activity in Android (two implementations) Today I will continue to introduce EventBus, another way to achieve this effect. (Compared with handler, interface callback, bundle parameter, this is easy to use to cry)
EventBus is an efficient message bus for publish/subscribe events under Android. The function is to replace the traditional Intent,Handler,Broadcast or interface functions to transfer data between Fragment, Activity, Service and thread to communicate and execute methods. As a message bus, there are three main elements:
(1) Event: Events
(2) Subscriber: Event Subscriber, accepting specific events
(3) Publisher: Event publisher, used to notify Subscriber that an event has occurred
Combining the above three elements of EventBus, we can also call it an observer design pattern.
EventBus official website link http://greenrobot.org/eventbus/
EventBus GitHub link https://github.com/greenrobot/EventBus
Previous related blog links:
Interaction between Fragment and Activity in Android (two implementations)
Two Ways to Create Fragment s in Android
2.Demo example
3. Implementation steps
Demo Architecture:
3.1 Lead Dependency Package
Use Android Studio 2.2. Still, add the following code directly under dependencies under build.gradle:
compile 'org.greenrobot:eventbus:3.0.0'
Dependency addition is completed after synchronization.
3.2 Layout File
(1) Main layout file, activity_main.xml file in layout
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" tools:context="com.mly.panhouye.eventbustest.MainActivity"> <LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical" android:background="#6f6669"> <Button android:layout_gravity="center_horizontal" android:id="@+id/panhouye" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="ŋ" /> <Button android:layout_gravity="center_horizontal" android:id="@+id/bikonghai" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="̿պ" /> <Button android:layout_gravity="center_horizontal" android:id="@+id/postSticky" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="ճДʂ" /> </LinearLayout> <FrameLayout android:id="@+id/framelayout" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="2"></FrameLayout> </LinearLayout>
(2) The fragment layout file fragment_msg.xml file on the right side of the layout
<?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/tv" android:layout_width="match_parent" android:layout_height="match_parent" android:text="no data" android:textSize="50sp" android:gravity="center_horizontal"/> </LinearLayout>
(3) Viscous Event Demonstration Interface layout activity_main2.xml File in layout
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main2" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.mly.panhouye.eventbustest.Main2Activity"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:textSize="30sp" android:gravity="center_horizontal" android:id="@+id/tv" android:text="no data"/> </RelativeLayout>
3.3 Java implementation code
(1) Customize event classes
The simplest event in this demonstration is publishing. Events only publish string data. MessageEvent.java file is as follows:
package com.mly.panhouye.eventbustest; /** * Created by panchengjia on 2017/2/19 0019. */ public class MessageEvent { String data; public MessageEvent(String data) { this.data = data; } }
(2)MsgFragment.java
In addition to associating the corresponding fragment layout with the java class corresponding to the fragment on the right side, we need to add methods to modify the text of the fragment as follows:
package com.mly.panhouye.eventbustest; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; /** * Created by panchengjia on 2017/2/20 0020. */ public class MsgFragment extends Fragment { TextView tv; @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_msg,container,false); tv = (TextView) view.findViewById(R.id.tv); return view; } public void setText(String message){ tv.setText(message); } }
(3)MainActivity.java
MainActivity.java's corresponding layout is the main layout, and the fragment on the right is attached to the layout. Therefore, it is necessary to register EventBus in this class and current Activity as event subscriber. The specific code is as follows:
package com.mly.panhouye.eventbustest; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; public class MainActivity extends AppCompatActivity implements View.OnClickListener { Button panhouye,bikonghai,postSticky; MsgFragment msgFragment; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); panhouye= (Button) findViewById(R.id.panhouye); bikonghai= (Button) findViewById(R.id.bikonghai); postSticky= (Button) findViewById(R.id.postSticky); panhouye.setOnClickListener(this); bikonghai.setOnClickListener(this); postSticky.setOnClickListener(this); //Add to fragment To the frame layout on the right msgFragment = new MsgFragment(); getSupportFragmentManager().beginTransaction().add(R.id.framelayout,msgFragment).commit(); } /*Personal recommendation to register EventBus in onResume *Register in visible interactive state with as little memory as possible */ @Override protected void onResume() { super.onResume(); EventBus.getDefault().register(this); } /*Personal suggestion is to register EventBus in onPause (register current Activity as event subscriber) *Remove the registration as early as possible without affecting the function and occupy as little memory as possible. */ @Override protected void onPause() { super.onPause(); EventBus.getDefault().unregister(this); } /** * Event Publisher (event publishing by clicking event buttons) * @param v */ @Override public void onClick(View v) { switch (v.getId()){ //(1)The parameters passed in event publishing can be used as the right side fragment Text modification //(2)Parameters passed in event publishing can also be used as discriminatory notifications for event subscriber execution methods case R.id.panhouye: EventBus.getDefault().post(new MessageEvent("Pan Hou Ye")); break; case R.id.bikonghai: EventBus.getDefault().post(new MessageEvent("Blue sky sea")); break; case R.id.postSticky: //Sticky Event Release EventBus.getDefault().postSticky(new MessageEvent("Sticky event")); startActivity(new Intent(this,Main2Activity.class)); break; } } /** * Event Subscriber Customized Receiving Method * @param event */ @Subscribe(threadMode = ThreadMode.MAIN) public void onMessageEvent(MessageEvent event) { // //(1)Modify data published by event publishers as text // msgFragment.setText(event.data); //(2)Distinguishing Method Execution from Data Published by Event Publishers switch(event.data){ case "Pan Hou Ye": msgFragment.setText("panhouye"); break; case "Blue sky sea": msgFragment.setText("bikonghai"); break; } } }
(4)Main2Activity.java
Note: As a subscriber to sticky event publishing, this layout also needs to register EventBus.
package com.mly.panhouye.eventbustest; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.TextView; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; public class Main2Activity extends AppCompatActivity { TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); tv = (TextView) findViewById(R.id.tv); } @Override protected void onResume() { super.onResume(); EventBus.getDefault().register(this); } @Override protected void onPause() { super.onPause(); EventBus.getDefault().unregister(this); } @Subscribe(threadMode = ThreadMode.MAIN,sticky = true) public void onMessageEvent(MessageEvent event) { // //(1)Modify data published by event publishers as text tv.setText(event.data); //(2)Distinguishing Method Execution from Data Published by Event Publishers // switch(event.data){ // case "Sticky event": // tv.setText("panhouye"); // break; // } } }
Published sticky events are automatically passed to new subscribers after their new subscribers are registered. Sometimes we need to remove sticky events to prevent them from passing on.
MessageEvent stickyEvent = EventBus.getDefault().getStickyEvent(MessageEvent.class); // Better check that an event was actually posted before if(stickyEvent != null) { // "Consume" the sticky event EventBus.getDefault().removeStickyEvent(stickyEvent); // Now do something with it } MessageEvent stickyEvent = EventBus.getDefault().removeStickyEvent(MessageEvent.class); // Better check that an event was actually posted before if(stickyEvent != null) { // Now do something with it }
4. Thread mode
EventBus provides four threading modes:
(1) postThread: The user will be called in the same thread, which is the publish event (which is the default value). Event passing implies minimal overhead because it completely avoids thread switching. Therefore, this is the recommended pattern to handle simple tasks, if it is known to be completed in a very short time, without requiring the main thread. Event processing using this pattern must return quickly to avoid blocking the publishing thread, which may be the main thread.
(2) MainThread: The user will be called in the main thread (UI thread). If the publishing thread is the main thread, the event handler method will be invoked directly. Event handlers using this pattern must return quickly to avoid blocking the main thread.
(3) BackgrounThread: The subscriber will be invoked in the background thread. If the publishing thread is not the main thread, the event handler method will be invoked directly in the publishing thread. If the thread is the main thread, eventbus uses a separate background thread and will call all events sequentially. Event handlers using this pattern should try to return quickly to avoid blocking background threads.
(4) Async: The event handler method is invoked in a separate thread. This is always independent of the publishing thread and the main thread. Publishing events never wait for an event handler method that uses this pattern. Event handler methods use this pattern if their execution may take some time, such as for network access. Avoid triggering a large number of asynchronous handler methods that run for a long time at the same time to limit the number of concurrent threads. Evetbus uses a thread pool to effectively reuse threads notified by completed asynchronous event handlers.