Insider's Guide To Udacity Android Developer Nanodegree Part 3 - Making the Baking App
Insider's Guide To Udacity Android Developer Nanodegree Part 3 - Making the Baking App
Written by Nikos Vaggalis   
Monday, 03 July 2017
Article Index
Insider's Guide To Udacity Android Developer Nanodegree Part 3 - Making the Baking App
Step 1 - Fragments
Fragments In Action
Layouts
Fragments
Step 2 - Libraries & Networking
POJO To Parcelables
Step 3 - Adding Exoplayer
Step 4 - Widgets
Step 5 - The Widget Provider
Step 6 - UI Testing
Step 7 - Testing Intents



The next and last step in this chain of conversions is do the same from POJO to Parcelable.Well there's a converter for that too! Head over to www.parcelabler.com, paste each of the Recipe, Ingredient and Step Java classes into its webform and viola, we got our Parcelables back!

image16
As a sample of the generated files, let's take a look at what Ingredient.java class was converted to:


/****
Ingredient POJO turned Parcelable
****/

package com.example.android.recipe.pojo;


import android.os.Parcel;
import android.os.Parcelable;

public class Ingredient implements Parcelable {

    private Double quantity;
    private String measure;
    private String ingredient;

    public Double getQuantity() {
        return quantity;
    }

    public void setQuantity(Double quantity) {
        this.quantity = quantity;
    }

    public String getMeasure() {
        return measure;
    }

    public void setMeasure(String measure) {
        this.measure = measure;
    }

    public String getIngredient() {
        return ingredient;
    }

    public void setIngredient(String ingredient) {
        this.ingredient = ingredient;
    }


    protected Ingredient(Parcel in) {
        quantity = in.readByte() == 0x00 ?
                           null : in.readDouble();
        measure = in.readString();
        ingredient = in.readString();
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(
                      Parcel dest, int flags) {

        if (quantity == null) {
            dest.writeByte((byte) (0x00));
        } else {
            dest.writeByte((byte) (0x01));
            dest.writeDouble(quantity);
        }
        dest.writeString(measure);
        dest.writeString(ingredient);
    }

    @SuppressWarnings("unused")
    public static final Parcelable.Creator<Ingredient>
       CREATOR = new Parcelable.Creator<Ingredient>() {
        @Override
        public Ingredient createFromParcel(Parcel in) {
            return new Ingredient(in);
        }

        @Override
        public Ingredient[] newArray(int size) {
            return new Ingredient[size];
        }
    };
}


I didn't wrap those objects into Parcelables for fun. I did it so that a ParcelableArrayList of Recipe super objects can cross Activities and Fragment boundaries, initially from RecipeActivity


/****
RecipeActivity/RecipeFragment
****/

 recipe.enqueue(new Callback<ArrayList<Recipe>>() {
            @Override
            public void onResponse(Call<ArrayList<Recipe>> call,
                                 Response<ArrayList<Recipe>> response) {
              ....
                ArrayList<Recipe> recipes = response.body();

                Bundle recipesBundle = new Bundle();
                recipesBundle.putParcelableArrayList(
                                                        ALL_RECIPES, recipes);
            ...

            }
           


to RecipeDetailActivity and RecipeDetailFragment so that I can extract both the list of Ingredients and Steps to fill their associated views:
   


/****
RecipeDetailActivity/RecipeDetailFragment
****/

        if(savedInstanceState != null) {
            recipe = savedInstanceState
                 .getParcelableArrayList(SELECTED_RECIPES);
        }
        else {
            recipe =getArguments()
                  .getParcelableArrayList(SELECTED_RECIPES);
        }

        List<Ingredient> ingredients = recipe.get(0).getIngredients();
        recipeName=recipe.get(0).getName();

        View rootView = inflater.inflate(
              R.layout.recipe_detail_fragment_body_part, container, false);
        textView = (TextView)rootView.findViewById(
                                                            R.id.recipe_detail_text);

        ArrayList<String> recipeIngredientsForWidgets=
                                                                       new ArrayList<>();

        ingredients.forEach((a) ->
            {
                textView.append("\u2022 "+ a.getIngredient()+"\n");
                textView.append("\t\t\t Quantity:"
                              +a.getQuantity().toString()+"\n");
                textView.append("\t\t\t Measure: "
                              +a.getMeasure()+"\n\n");

                recipeIngredientsForWidgets.add(
                         a.getIngredient()+"\n"+
                        "Quantity: "+a.getQuantity().toString()+"\n"+
                        "Measure: "+a.getMeasure()+"\n");
            });

        recyclerView=(RecyclerView)rootView.findViewById(
                                                        R.id.recipe_detail_recycler);
        LinearLayoutManager mLayoutManager=
                                   new LinearLayoutManager(getContext());
        recyclerView.setLayoutManager(mLayoutManager);

        RecipeDetailAdapter mRecipeDetailAdapter=
            new RecipeDetailAdapter((RecipeDetailActivity)getActivity());
        recyclerView.setAdapter(mRecipeDetailAdapter);
        mRecipeDetailAdapter.setMasterRecipeData(
                                                     recipe,getContext());


Two extra notes on the lambda expression used. The Jack compiler, ?which is now deprecated in the latest version of Android Studio, is still necessary for enabling for Java 8 features such as lambdas, but this also has the side effect of disabling the Android Studio's 'instant run' feature, therefore a full project re-compilation is necessary every time something has changed. This increases the time spent on the building phase of the project.

Initially I aimed for:

     
  Integer count=new Integer();
   
        ingredients.forEach((a) ->
            {  
                count=count+1;
                mTextView.append(count.toString(),
                         +" "+a.getIngredient()+"\n");
                mTextView.append("\t\t Quantiy: "
                        +a.getQuantity().toString()+"\n");
                mTextView.append("\t\t Measure: "
                        +a.getMeasure()+"\n\n");
            });
           

which would print sequence numbers in front of each ingredient. But the compiler complained that 'count' should be final therefore it cannot be assigned within the lambda's scope, in effect turning off closures. As it turns out, Java can't close over variables so in reality it has got limited closures. Scrapping that, I went with just printing a dot in front of each ingredient with "\u2022 "



Last Updated ( Tuesday, 04 July 2017 )
 
 

   
Banner
RSS feed of all content
I Programmer - full contents
Copyright © 2017 i-programmer.info. All Rights Reserved.
Joomla! is Free Software released under the GNU/GPL License.