Android Routing and Data Passing

0
User Management System
Learn Kotlin, Retrofit, MVVM and MySQL using this all-in-one app. It is designed to be beginner friendly.

In any type of significant project, you will certainly need more than one page. These pages we represent them using Activity or Fragment in android. Routing in this context is the act of navigating from one page to another. The page may be either an activity or fragment.

Data passsing involves passing data from one page to another. That data may be simple primitive types like strings and integers or custom objects, like say a Student or Teacher. You typically use intent and bundles in android but their are libraries that make this process easier, more flexible and less error prone. In this piece we look at these.

  • Solution One
  • Example

(a). CachePot

Questions CachePot helps answer.

Here is a summary of the problems cachepot helps you answer:

  1. How to Pass Data Between Activities
  2. How to Pass Data Between Fragments
  3. How to pass multiple data types between activities/fragments.
  4. How to Pass Data Between Activities and Fragments
  5. How to Pass Data From PageAdapter to Fragments.

Difference to other similar Libraries

  1. Its easy to use.
  2. Complete, encompassing both fragments and activities.
  3. Ability to pass single or multiple data or types. Easily pass custom objects or collections for example.
  4. No annotations or extension of classes.

CachePot - Android Simple Data Cache

Build Status Download
API

CachePot is a simple open source for data cache management and passing data object between Fragments(Activities) without Pacelable and Serializable.

WARNING: It would be inappropriate to pass data both ways between different android applications, it's a better way to use Intent properly.

Download

Gradle:

repositories {
  jcenter()
}

dependencies {
  compile 'com.github.kimkevin:cachepot:1.2.0’
}

Maven:

<dependency>
  <groupId>com.github.kimkevin</groupId>
  <artifactId>cachepot</artifactId>
  <version>1.2.0</version>
</dependency>

Usage

It works anywhere. there're examples as below

  • Between Activity and Activity
  • Between Activity and Fragment
  • Between Fragment and Fragment
  • From PagerAdapter to individual Fragment

1. Single Type, Single Data

Push your data object to CachePot instance in your Activity or Fragment.

public void push(Object data)

KoreanFood foodItem = new KoreanFood(1, "Kimchi", "Traditional fermented Korean side dish made of vegetables")  
CachePot.getInstance().push(foodItem);
// open your activity or fragment

Pop your data object from CachePot after view changes

public Object pop(Class classType)

public class MainFragment extends Fragment{
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        KoreanFood foodItem = CachePot.getInstance().pop(KoreanFood.class);
    }

In case of Collection or Map

Push

List<KoreanFood> foodItems = new ArrayList<>();
foodItems.add(new KoreanFood(1, "Kimchi", "Traditional fermented Korean side dish made of vegetables"));
foodItems.add(new KoreanFood(2, "Kkakdugi", "A variety of kimchi in Korean cuisine"));

CachePot.getInstance().push(foodItems);
// open your activity or fragment

Pop

List<KoreanFood> foodItems = CachePot.getInstance().pop(ArrayList.class);

2. Single Type, Multiple Data

How to pass Object(Model) Asynchronously when using ViewPager

First push your data object with position or id to CachePot instance in FragmentStatePagerAdapter(or FragmentPagerAdapter)

public void push(long id, Object data)

private class PagerAdapter extends FragmentStatePagerAdapter {
    ...
    public Fragment getItem(int position) {
        KoreanFood foodItem = foodItems.get(position);
        CachePot.getInstance().push(position, foodItem);
        // or
        CachePot.getInstance().push(foodItem.getId(), foodItem);
        ...
    }
}

public Object pop(long id)

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...
    if (getArguments() != null) {
        final int position = getArguments().getInt(ARG_POSITION);
        foodItem = CachePot.getInstance().pop(position);
        // or
        foodItem = CachePot.getInstance().pop(id);
    }
}

If more complecated views, use TAG

public void push(String tag, Object data) public void push(String tag, long id, Object data)

private class PagerAdapter extends FragmentStatePagerAdapter {
    ...
    public Fragment getItem(int position) {
        KoreanFood foodItem = foodItems.get(position);
        CachePot.getInstance().push(TAG, position, foodItem);
        // or
        CachePot.getInstance().push(TAG, foodItem.getId(), foodItem);
        ...
    }
}

public Object pop(String tag) public Object pop(String tag, long id)

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...
    if (getArguments() != null) {
        final int position = getArguments().getInt(ARG_POSITION);
        foodItem = CachePot.getInstance().pop(TAG, position);
        // or
        foodItem = CachePot.getInstance().pop(TAG, id);
    }
}

Contributing

All contributions are welcome. Open a Pull Requests or refer to the Issues section.

License

MIT Copyright (c) 2016-present, “KimKevin” Yongjun Kim

Here is a usage example in a Fragment:


public class FoodFragment extends Fragment {
  private static final String TAG = FoodFragment.class.getSimpleName();

  private static String ARG_POSITION = "position";

  private TextView txt;
  private Button btn;

  private KoreanFood koreanFoodItem;

  public static FoodFragment newInstance(int position) {
    FoodFragment fragment = new FoodFragment();
    Bundle args = new Bundle();
    args.putInt(ARG_POSITION, position);
    fragment.setArguments(args);
    return fragment;
  }

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (getArguments() != null) {
      final int position = getArguments().getInt(ARG_POSITION);

      koreanFoodItem = CachePot.getInstance().pop(position);
    }
  }

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_food, container, false);

    txt = (TextView) rootView.findViewById(R.id.main_txt);
    btn = (Button) rootView.findViewById(R.id.main_btn);

    return rootView;
  }

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

    if (koreanFoodItem == null) return;

    txt.setText("It's " + koreanFoodItem.getName());
    btn.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        CachePot.getInstance().push(koreanFoodItem);

        NaviUtil.addFragment(getActivity(), new FoodDetailFragment());
      }
    });
  }
}

Here is another example usage with a page adapter:


public class JarFragment extends Fragment {
  private static final String TAG = JarFragment.class.getSimpleName();

  private ViewPager mViewPager;

  private List foodItems;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    foodItems = new ArrayList<>();
    foodItems.add(new KoreanFood(1, "Kimchi", "Traditional fermented Korean side dish made of vegetables"));
    foodItems.add(new KoreanFood(2, "Kkakdugi", "A variety of kimchi in Korean cuisine"));
  }

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_main, container, false);
    mViewPager = (ViewPager) rootView.findViewById(R.id.main_pager);

    return rootView;
  }

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

    PagerAdapter mPagerAdapter = new PagerAdapter(getFragmentManager());
    mViewPager.setAdapter(mPagerAdapter);
  }

  private class PagerAdapter extends FragmentStatePagerAdapter {
    public PagerAdapter(FragmentManager fm) {
      super(fm);
    }

    @Override
    public Fragment getItem(int position) {
      /**
       * Put your Obejct with Position to DataCache
       */
      CachePot.getInstance().push(position, foodItems.get(position));

      return FoodFragment.newInstance(position);
    }

    @Override
    public int getCount() {
      return foodItems.size();
    }
  }
}

Find full example in the download

 

  • Example

(b). RxRouter

Questions RxRouter helps solve

Here are the common problems RxRouter makes easier:

  1. How to pass data between activities
  2. Alternative to onActivityResult
  3. How to route through classes as well as system and custom actions.

What makes RxRouter Unique

Here are the features that stand out in RxRouter:

  1. Easy to use
  2. Uses reactive programming
  3. Provides routing via annotations
  4. Pass multiple parameters between activities.
  5. Can route through system and custom actions.
  6. Firewall system - the ability to intercept a route.

RxRouter

Download

Read this in other languages: 中文English 

A lightweight, simple, smart and powerful Android routing library.

Getting started

Setting up the dependency

Add to your project build.gradle file:

dependencies {
    implementation 'zlc.season:rxrouter:x.y.z'
    annotationProcessor 'zlc.season:rxrouter-compiler:x.y.z'
}

(Please replace x and y and z with the latest version numbers: )

For Kotlin you should use kapt instead of annotationProcessor

Hello World

First add the @url annotation to the activity we need to route:

@Url("this is a url")
class UrlActivity : AppCompatActivity() {
    ...
}

Then create a class that is annotated with @Router to tell RxRouter that there is a router:

@Router
class MainRouter{
}

This class doesn't need to have any remaining code. RxRouter will automatically generate a RouterProvider based on the class name of the class. For example, MainRouter will generate MainRouterProvider.

Then we need to add these routers to RxRouterProviders:

class CustomApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        RxRouterProviders.add(MainRouterProvider())
    }
}

Finally, we can start our performance:

RxRouter.of(context)
        .route("this is a uri")
        .subscribe()

Parameters

Routing with parameters:

With the with method, you can add a series of parameters to this route.

RxRouter.of(context)
        .with(10)                           //int value
        .with(true)                         //boolean value
        .with(20.12)                        //double value
        .with("this is a string value")     //string value
        .with(Bundle())                     //Bundle value
        .route("this is a uri")
        .subscribe()

No longer needs the onActivityResult method

Want to get the value returned by the route? No longer have to write a bunch of onActivityResult methods! One step in place with RxJava!

RxRouter.of(context)
        .with(false)
        .with(2000)
        .with(9999999999999999)
        .route("this is a uri")
        .subscribe {
            if (it.resultCode == Activity.RESULT_OK) {
                val intent = it.data
                val stringResult = intent.getStringExtra("result")
                result_text.text = stringResult
                stringResult.toast()
            }
        }

If there is a result return, it will be processed in subscribe.

Routing through Class

Do not want to use Url annotations? No problem, RxRouter also supports the original jump of the specified class name, in the same way:

RxRouter.of(context)
        .routeClass(ClassForResultActivity::class.java)
        .subscribe{
            if (it.resultCode == Activity.RESULT_OK) {
                val intent = it.data
                val stringResult = intent.getStringExtra("result")
                result_text.text = stringResult
                stringResult.toast()
            }
        }

Routing through Action

Similarly, RxRouter also supports system Actions and custom Actions.

Routing through custom Action:

<activity android:name=".ActionActivity">
    <intent-filter>
        <action android:name="zlc.season.sample.action" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>
RxRouter.of(context)
        .routeAction("zlc.season.sample.action")
        .subscribe({
            "no result".toast()
        }, {
            it.message?.toast()
        })

Routing through system action:

//dial
RxRouter.of(this)
        .addUri(Uri.parse("tel:123456"))
        .routeSystemAction(Intent.ACTION_DIAL)
        .subscribe()

//send message
val bundle = Bundle()
bundle.putString("sms_body", "this is message")
RxRouter.of(this)
        .addUri(Uri.parse("smsto:10086"))
        .with(bundle)
        .routeSystemAction(Intent.ACTION_SENDTO)
        .subscribe()

Firewall

The RxRouter has a small and powerful firewall that can be intercepted according to firewall rules before routing. You can add one or more firewalls.

//create a LoginFirewall
class LoginFirewall : Firewall {
    override fun allow(datagram: Datagram): Boolean {
        if (notLogin) {
            "please log in".toast()
            return false
        }
        return true
    }
}

//Add Firewall to Route
RxRouter.of(this)
        .addFirewall(LoginFirewall())
        .route("this is a url")
        .subscribe()

License

Copyright 2018 Season.Zlc

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Android MySQL Retrofit2 Multipart CRUD,Search,Pagination rating

When I was a 2nd year Software Engineering student, I buillt a now defunct online tool called Camposha(from Campus Share) using my then favorite language C#(ASP.NET) to compete OLX in my country(Kenya). The idea was to target campus students in Kenya. I got a few hundred signups but competing OLX proved too daunting. I decided to focus on my studies, learning other languages like Java,Python,Kotlin etc while meanwhile publishing tutorials at my YouTube Channel ProgrammingWizards TV which led to this site(camposha.info). Say hello or post me a suggestion: oclemmi@gmail.com . Follow me below; Github , and on my channel: ProgrammingWizards TV

We will be happy to hear your thoughts

Leave a reply

12 − = seven

Reset Password
Compare items
  • Total (0)
Compare
0
Shopping cart