Fragment-based Android front-end service framework

Source: Internet
Author: User

Starting from Android 3.0, Google introduced a brand new fragment UI system to reinterpret reusable and extensible Android UI design concepts. The android support Library provides a complete post-fragment compatibility solution (backport) for any lower-version Android app developers ). Therefore, if you develop a new Android Application, you do not have to worry about using fragment. Embracing this powerful mechanism design as early as possible can help you save considerable development and maintenance workload.

When talking about the service framework, you may already be familiar with it, but it is somewhat surprising to associate it with fragment. Let's take a look at the existing standard service framework of Android, which is generally called a background service. The definition in the official document is: an application component that can be operated for a long time in the background and does not provide the UI. The main feature of the service is that the lifecycle is independent from the application UI and does not end with the application exiting. The typical functions of background services are as follows: execute tasks (such as downloading and playing) that are not interrupted by application switching, or listen to and respond to system events (such as powered by electricity and location ). However, in actual development, the implementation complexity of the service is not low. On the one hand, we need to consider and process the service lifecycle, and on the other hand, we need to handle the communication between the service and the UI, if you need to interact with users in Service Code, either use the toast and notification mechanisms that are quite limited, or implement a complex UI callback ......

In fact, in most application scenarios, many UI-related processing (that is, controller in MVC) have the same cross-interface multiplexing and sharing requirements as background services, they are also closely related to the UI and only play a role when the application is opened, such as the global status of the Account, unread notification messages, and shopping cart. This kind of requirement is generally called the foreground service ). In the past, some of these requirements were shared across different interfaces using sharedpreference. This not only has some additional overhead (file IO ), at the same time, the data type and logic are obviously limited. In addition, when the status is complex, the performance cost of rebuilding the status after each status switch (such as screen rotation) may also affect the user experience.

In fact, the fragment mechanism can perfectly meet the requirements of the above-mentioned front-end services. Thanks to the close connection between fragment itself and the interface, it can easily achieve two-way communication between services and the UI; benefit from the automatic lifecycle management of fragment, so you do not have to guard against memory leaks. With the retain switching mechanism of fragment, you can ensure that the service is not suspended during status switching. In addition, because the fragment lifecycle management is automatically completed by the framework, developers do not have to add redundant services in the activity lifecycle Event code, make the code simpler and clearer.The only restriction is that fragment cannot be shared across activities.However, according to the fragment-based interface design philosophy, all associated UI components should be implemented based on fragment and placed under a common activity, A separate activity is required only on the interface that can exist and continue independently in the lifecycle. Therefore, this restriction is not a real problem in apps developed in strict accordance with the fragment design philosophy.

If you still have a reserved opinion on fragment's "special purpose", you may wish to see this section in the official document: "adding a fragment without UI 』, it explicitly implies the rationality and feasibility of this method.

Next, let's explore a feasible fragment-based front-end service framework.

(1) Create, destroy, and obtain front-end services

Similar to background services, foreground services are usually created on demand. Therefore, service creation and retrieval can be encapsulated in an operation. Because fragment without UI cannot be accessed by the resource ID of the embedded point on the interface, tags are usually the only reliable identification and access method. (Some exception handling is omitted in the following code)

private static final String KServiceTagPrefix = "service:";public static <T> T getService(Class service_class, FragmentManager fm) {  final String service_name = KServiceTagPrefix + service_class.getCanonicalName();  @SuppressWarnings("unchecked") T service = (T) fm.findFragmentByTag(service_name);  if (service == null) {    Log.i(TAG, "Starting service: " + service_class.getSimpleName());    service = service_class.newInstance();    FragmentTransaction transaction = fm.beginTransaction();    transaction.add(service, service_name);    transaction.commit();    fm.executePendingTransactions();  }  return service;}

Note: executependingtransactions () is used to ensure that the service object completes the basic initialization lifecycle before being returned to the caller.

When foreground services are required in an activity or other fragment, you can call the above static method to ensure that there is only one service instance throughout the activity lifecycle, therefore, we directly use the class of the front-end service as its identifier. You can use getsupportfragmentmanager () in fragmentactivity to obtain another parameter that needs to be passed in the call. You can use getfragmentmanager () in fragment.

Considering that the passive life cycle of fragment is terminated with the destruction of the activity, the life cycle of the activity of the app is usually short, therefore, you do not need to introduce a complex mechanism such as reference count to maintain the termination time of the front-end service.

(2) interaction between the UI element and the front-end service

Access the front-end service from the UI element. You can simply use the obtained service instance and call the method. Service instance references can be securely stored in activity or fragment objects of the same source, but do not save them in objects that have a longer life cycle than the parent activity, such as static members.

In turn, accessing the UI elements from the front-end service is slightly more elegant. Access to the activity is the simplest. You can use the getactivity () method to obtain the activity instance, therefore, we can easily give user-friendly instructions on the front-end service processing process using the "Progress circle" (indeterminate progress) on the activity interface. For other fragment access, the official documentation mentions the use of settargetfragment () and gettargetfragment (), but in the foreground service scenarios, especially considering issues such as sharing, decoupling, and concurrency, this is not a good solution. Most developers may be more likely to think of the "Callback mode". For example, it is also a feasible solution to provide the callback registration interface in the foreground service class, however, individuals prefer to use the flexible and easy-to-use localbroadcastmanager to implement service-oriented notifications to the UI. We will not introduce this mechanism here. If you are interested, you can directly look at Android.
Support library javadoc.

(3) Implement Service persistence for cross-state switching

As front-end services do not directly involve the interface layout, they do not need to be rebuilt during status switching such as screen rotation, thus effectively reducing the experience delay in this process. Implementation is actually very simple. You only need to set itself to "maintainable" during the fragment initialization process 』:

@Override public void onCreate(final Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setRetainInstance(true);}
(4) use with the loader Mechanism

The loader mechanism is also a practical auxiliary mechanism added in Android 3.0, which can help developers achieve better coordination between asynchronous Io and UI components. Like the (same process) service mechanism, the front-end service entry code is also executed in the main thread (ui thread), So I/O operations must be avoided as much as possible. With the help of the loader mechanism, I/O, especially network access, can be well isolated to an independent work thread, and convenient collaboration with the UI components is also taken into account, therefore, the front-end service and the loader mechanism are an excellent partner. However, in actual use, there are also some details that need attention. improper use may also cause some exceptions that are difficult to troubleshoot.

When using loadermanager, You need to clearly distinguish whether you want to use activity-level loadermanager or local fragment (Front-End Service)-level loadermanager. Unlike the uniformity of fragmentmanager, they are actually two different instances, it has different effects. In most cases, loader is only used by this front-end service. Therefore, using loadermanager at the fragment level is the best choice. If you want to reuse some loaders (such as cursorloader) between multiple front-end services, you must use activity-level loadermanager, but be careful not
Id conflict.

 

The above is a summary of the Preliminary Exploration of the front-end service framework based on fragment some time ago. This mechanism has been running normally for a while in an app I recently developed, no significant problems or elbows were found during this period. If you have encountered any doubts or difficulties while learning from the above mechanisms, please feel free to discuss with me. I will also improve the relevant experience and skills in this article.

Appendix: complete code of servicefragment abstract base class

public abstract class ServiceFragment extends Fragment {  private static final String KServiceTagPrefix = "service:";  @Override public void onCreate(final Bundle state) {    super.onCreate(state);    setRetainInstance(true);  }  /** @see {@link android.support.v4.content.LocalBroadcastManager#sendBroadcast(Intent)} */  protected boolean sendLocalBroadcast(final Intent intent) {    return LocalBroadcastManager.getInstance(getActivity()).sendBroadcast(intent);  }  public static <T extends ServiceFragment> T getService(final Class<T> service_class, final FragmentManager fm) {    if (fm == null) throw new IllegalArgumentException("FragmentManager is null");    final String service_name = KServiceTagPrefix + service_class.getCanonicalName();    @SuppressWarnings("unchecked") T service = (T) fm.findFragmentByTag(service_name);    if (service == null) {      Log.i(TAG, "Starting service: " + service_class.getSimpleName());      try {        service = service_class.newInstance();      } catch (final java.lang.InstantiationException e) {        throw new IllegalArgumentException(service_class + " cannot be instantiated");      } catch (final IllegalAccessException e) {        throw new IllegalArgumentException(service_class + " is inaccessible");      }      final FragmentTransaction transaction = fm.beginTransaction();      transaction.add(service, service_name);      transaction.commit();      fm.executePendingTransactions();    }    return service;  }  private static final String TAG = ServiceFragment.class.getSimpleName();}
From: http://blog.oasisfeng.com/2012/10/02/android-service-framework-based-on-fragment/
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.