Sunday, 5 April 2020

Post 79: What some people don't know about Polymorphism

In the context of programming, polymorphism means - in abstract terms - when programming constructs or part of a code, e.g. classes or methods, can be applied to multiple Objects of different types. Usually this is where the knowledge of most people end. Most people don't know there are different kinds of polymorphism. In this post I'll explain the different types of polymorphism and discuss the advantages and disadvantages of each one of them:

Subtype-Polymorphism
If people talk about polymorphism, they usually mean this type of polymorphism. This is also the most simplest kind of polymorphism. When subtyping, an object of a subtype can be used everywhere where it's supertype is used. For example:

class Supertype {}
class Subtype extends Supertype {}
...
Supertype sup1 = new Supertype();
Supertype sup2 = new Subtype(); 

In the example above, Subtype can be used where Supertype is used.

Another is example:
class MyObject1 {}
class MyObject2 {}

MyObject1 o1 = new MyObject1();MyObject2 o2 = new MyObject2();List<Object> obList = new ArrayList<>();obList.add(o1);obList.add(o2);obList.add(2);obList.add("hello");

In the above example obList can take objects of different types - from custom objects to numbers to String.

Advantages
  • Subtype-Polymorphism gives you flexibility

Disadvantages
  • It's hard to limit the flexibility
  • You lose type safety, because you only have limited control of which object is allowed to be added to a container and if you take an object out of a container, you have to cast it to it's original type in order to use it in a meaningful way
Parametic Polymorphism

Sometimes you want to reuse a class for different types but don't want to write for every type a class of their own. So, basically you only want to swap out certain parameters for a specific type. This is what parametic polymorphism is about.

When creating a class, you set a generic type T. Within the class you treat the generic type like any other type. When initializing you specify the generic type T to a specific type. For example:

public class MyObject1<T> {
    T obj;    void setObj(T obj) {
        this.obj = obj;
    }

    T getObj() {
        return this.obj;
    }
}

Let's say you want to apply this class only to Integers, then you initialize it like the following:
MyObject1<Integer> object1 = new MyObject1<Integer>();

On another instance you want to reuse the same class but for another type, then you initilize it with a different class:

MyObject1<String> object2 = new MyObject1<String>();

You can use this technique not only for one type but also multiple types. For example:

public class KeyValue<K, V> {
    private K key;    private V value;        
    void setKeyValue(K key, V value) {
        this.key = key;
        this.value = value;
    }
    
    K getKey() {
        return this.key;
    }
    
    V getValue() {
        return this.value;
    }
}

Advantages

  • Usually a much more powerful type analysis at compile time

Disadvantages

  • Parametric polymorphism offers less flexibility compared to subtype polymorphism
  • The generic parameter doesn't know about the attributes and methods of the type that will be applied to at the end

Limited parametric polymorphism

The limited parametric polymorphism builds upon the parametic polymorphism and enables you to limit the typeparameter to a certain type by defining an upper bound for your type. This is useful when you want for example to build a container of different types and need to know the existence of certain attributes or methods beforehand.

For example you have a basket of different food products and want to know which of these elements is the oldest. Using limited parametric polymorphism, you would implement like this:
public interface Ageable {
    Date getBestBeforeDate();}

public class FoodBasket<T extends Ageable> {
    private T oldestFood;
    public void put(T food) {
        if (oldestFood == null ||
                food.getBestBeforeDate().compareTo(oldestFood.getBestBeforeDate()) < 0) {
            oldestFood = food;
        }

    }

    public T getOldestFood() {
        return oldestFood;
    }
}

By using extends we are creating an upper bound for our type. Thus we know that our type has to have the attributes or methods defined in the superclass resp. interface and can work them.

Let's say you want to use the basket for a specific kind of food and want to extend it with additional functionalities, the you would go about this:

public class Egg implements Ageable {
    private Date bestBeforeDate;
    Egg(Date bestBeforeDate) {
        this.bestBeforeDate = bestBeforeDate;    }

    @Override    public Date getBestBeforeDate() {
        return this.bestBeforeDate;    }
}

public class OldEggsBasket extends FoodBasket<Egg> {
    // additional functions}

Types can also implement multiple Interfaces:

public interface Printable {
    void print();}

public class FoodBasket<T extends Ageable & Printable> {
    private T oldestFood;
    public void put(T food) {
        if (oldestFood == null ||
                food.getBestBeforeDate().compareTo(oldestFood.getBestBeforeDate()) < 0) {
            oldestFood = food;        }
        food.print();    }
    //...
 }

Advantages

  • Write reusable code, e.g. library classes, that are used by other programmers who can parameterize according to their need

Disadvantages

  • Less flexibility in comparison to the above mentioned kinds of polymorphism




Ad-hoc Polymorphism

Most developers probably know this concept already under a different name: overloading. With overloading you are providing the different methods with the same name for different signatures. The most common one is the plus (+) operator.

Advantages

  • Flexibility in naming of (overloaded) methods
Disadvantages
  • No code reuse. Therefore isn't really considered polymorphism like the other kinds of polymorphism

I am interested whether you know more advantages and disadvantages for each of the types of polymorphism.

Sunday, 13 October 2019

Post 78: Syntax highlighting on Blogger

<pre class="brush: xml;">
<!-- escaped code here. For example: -->
<!-- https://www.freeformatter.com/html-escape.html -->
</pre>

Post 77: Percentage vertical layout

Percentagelayout is deprecated in Android, but you can achieve the same results with LinearLayout:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:weightSum="100"
        android:orientation="vertical"
        >

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="40"
            android:orientation="vertical">
            <Button
                android:id="@+id/btnPlayer2"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:text="Button" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="20"
            android:orientation="vertical">
            <Button
                android:id="@+id/btnStart"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:text="Button" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="40"
            android:orientation="vertical">

            <Button
                android:id="@+id/btnPlayer1"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:text="Button" />

        </LinearLayout>

    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

Friday, 4 October 2019

Post 76: Read from local resource in Android

In this post I'll show you how to read from local resource in Android. In this case it's a text file "text_file.txt" in the folder "raw" under the "res" folder.

private final Context helperContext = this; // put this on top of your class
....

final Resources resources = helperContext.getResources();
InputStream inputStream = resources.openRawResource(R.raw.text_file);

BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

try {
    String line = "";
    while ((line = reader.readLine()) != null) {
       System.out.println(line);
       // do something..., e.g. add in to an ArrayList
    }
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try {
        reader.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Post 75: Fetching data from Android app

Sometimes you want to fetch data from an API on some webserver from your Android app. Let say the server's adress is http://my-requested-data.com and let's say it returns you data in json format. This is how you do it:

        String url = "http://my-requested-data.com/?format=json";
       
        URL obj = new URL(url);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();
        // optional default is GET
        con.setRequestMethod("GET");
        //add request header
        con.setRequestProperty("User-Agent", "Mozilla/5.0");
        int responseCode = con.getResponseCode();

        BufferedReader in = new BufferedReader(
                new InputStreamReader(con.getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();
        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();

        //Read JSON response and print
        JSONObject myResponse = new JSONObject(response.toString());
//Access node from the json object:
        float finalResult = Float.parseFloat(myResponse.getString("some_predicate"));

Post 74: Convert datasets in text file into json file with python

Sometimes you want to convert datasets from text file to json.

Let's say you have the following input text file:

 Japan 83.74 80.91 86.58
 Italy 83.31 80 86.49
 Switzerland 82.84 80.27 85.23
 Singapore 82.66 80.43 84.74
 Israel 82.64 79.59 85.61
 Iceland 82.3 80.73 83.84
 Spain 82.28 79.42 85.05
 Australia 83.42 80.33 86.56
 Hong Kong 82.07 80.18 83.82
 Sweden 81.93 80.1 83.71
 France (metropol.) 81.85 78.76 84.87
 Canada 81.78 79.69 83.78
...

The datasets above have 4 columns. The first column has also a heading space that we need to get rid of. The columns are separated by tabs (\t) and each line is sepearted by line breaks (\n). To convert this datasets into and json output file, we write the following python script:

import json
import re

f=open("input.txt", "r")

arr = []
jsonResult = []

if f.mode == 'r':
    contents =f.read()
    arr = re.split(r'\n+', contents)
    print(arr)

arr = arr[:-1] # remove last element

for x in arr:
    line = re.split(r'\t+', x)
    print(line)
    country = line[0].strip() # remove heading and trailing spaces spaces
    expected_age_overall = line[1]
    expected_age_male = line[2]
    expected_age_female = line[3]
    json_item = {
        "country": country,
        "expected_age_overall": expected_age_overall,
        "expected_age_male": expected_age_male,
        "expected_age_female": expected_age_female
    }
    jsonResult.append(json_item)

 
print(jsonResult) # display the result

with open('output.json', 'w') as json_file:
    json.dump(jsonResult, json_file)


Friday, 27 September 2019

Post 73: How to create Android app that persistently saves custom objects

In almost any app you need to persistently save custom information in your app and later load it and display it to the user. Unfortunately Android doesn't provide you this functionality out of the box. Therefore in this tutorial I'll show you how to create an app that persistently saves custom objects with gson.
I'll use:

  1. Android studio
  2. android 28
  3. gson
  4. gradle


In it is mainly based on this post:

https://codinginflow.com/tutorials/android/save-arraylist-to-sharedpreferences-with-gson

But because some API has changed (for this have a look here: https://developer.android.com/jetpack/androidx/migrate/class-mappings) since then you won't be able to create an app if you follow the above mentioned tutorial. It took me a while to get it going. In order to save time, I create this tutorial for you. Also I added some additional information that was not mentioned in my reference post and that may be helpful for beginners.

First create a new app via android studio select the empty app template and call it "MyApplication".

Then add the following dependencies into your build.gradle file:

dependencies {
implementation 'com.android.support:design:28.0.+'
implementation 'com.google.code.gson:gson:2.8.5'
}

We need for our UI some designs that is not provided by the standard android SDK. Therefore we have to add the design dependency:
implementation 'com.android.support:design:28.0.+'

Google provides you with gson methods you can use to serialize and deserialize java objects
https://github.com/google/gson

Mind you, the number 28 in i.e. 'com.android.support:design:28.0.+' refers to your target SDK version. make sure that these are always the same number. In my example it's 28. Your's may differ. In order to know which target version you are using, you can also check in your gradle-file:

android {
    compileSdkVersion 28
    defaultConfig {
...
        targetSdkVersion 28
...
    }
}

Once you have added the above dependencies, click on the "sync" (at the top right corner) so gradle can download the needed dependencies.

The next step is to design our main layout. We want two input fields where we type in some data (that we will alter save) and two buttons: Insert and save. The Insert button inserts our newly created object into the list displayed in the main view. The save button saves it persistently on our app. In the "layout" folder write inside the "activity_main.xml" file this:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="de.pandaquests.myapplication.MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="100dp"
        android:background="@android:color/darker_gray" />

    <EditText
        android:id="@+id/edittext_line_1"
        android:layout_width="180dp"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="52dp"
        android:hint="Line 1" />

    <EditText
        android:id="@+id/edittext_line_2"
        android:layout_width="180dp"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentBottom="true"
        android:hint="Line 2" />

    <Button
        android:id="@+id/button_insert"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@id/edittext_line_1"
        android:layout_marginStart="13dp"
        android:layout_marginTop="23dp"
        android:layout_toEndOf="@id/edittext_line_1"
        android:text="insert" />

    <Button
        android:id="@+id/button_save"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@id/button_insert"
        android:layout_toEndOf="@+id/button_insert"
        android:text="save" />

</RelativeLayout>

Next is we create the UI for our custom element. The custom element represents the data we insert into the list. Create in the "layout" folder a file named "example_item.xml" by right clicking and choose new -> Layout resource file. Write "example_item.xml" as the name and ignore the rest, because we will overwrite everything insdie of that file with the following code inside of it:

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="4dp">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="4dp">

        <TextView
            android:id="@+id/textview_line1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Line 1"
            android:textColor="@android:color/black"
            android:textSize="20sp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/textview_line_2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/textview_line1"
            android:layout_marginStart="8dp"
            android:text="Line 2"
            android:textSize="15sp" />

    </RelativeLayout>

</androidx.cardview.widget.CardView>

Once we are done with that, we will create the needed functionality for our main activity. Inside the "MainActivity.java" file write the following:

package de.pandaquests.myapplication;

import android.content.SharedPreferences;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    ArrayList<ExampleItem> mExampleList;
    private RecyclerView mRecyclerView;
    private ExampleAdapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;

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

        loadData();
        buildRecyclerView();
        setInsertButton();

        Button buttonSave = findViewById(R.id.button_save);
        buttonSave.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                saveData();
            }
        });
    }

    private void saveData() {
        SharedPreferences sharedPreferences = getSharedPreferences("shared preferences", MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPreferences.edit();
        Gson gson = new Gson();
        String json = gson.toJson(mExampleList);
        editor.putString("task list", json);
        editor.apply();
    }

    private void loadData() {
        SharedPreferences sharedPreferences = getSharedPreferences("shared preferences", MODE_PRIVATE);
        Gson gson = new Gson();
        String json = sharedPreferences.getString("task list", null);
        Type type = new TypeToken<ArrayList<ExampleItem>>() {}.getType();
        mExampleList = gson.fromJson(json, type);

        if (mExampleList == null) {
            mExampleList = new ArrayList<>();
        }
    }

    private void buildRecyclerView() {
        mRecyclerView = findViewById(R.id.recyclerview);
        mRecyclerView.setHasFixedSize(true);
        mLayoutManager = new LinearLayoutManager(this);
        mAdapter = new ExampleAdapter(mExampleList);

        mRecyclerView.setLayoutManager(mLayoutManager);
        mRecyclerView.setAdapter(mAdapter);
    }

    private void setInsertButton() {
        Button buttonInsert = findViewById(R.id.button_insert);
        buttonInsert.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                EditText line1 = findViewById(R.id.edittext_line_1);
                EditText line2 = findViewById(R.id.edittext_line_2);
                insertItem(line1.getText().toString(), line2.getText().toString());
            }
        });
    }

    private void insertItem(String line1, String line2) {
        mExampleList.add(new ExampleItem(line1, line2));
        mAdapter.notifyItemInserted(mExampleList.size());
    }
}


You'll probably see lots of erros. But don't worry it's because there are still files missing. Next we create the "ExampleAdapter.java". Create in your project folder (the folder where also your MainActiviy.java file is) a file named "ExampleAdapter.java"

package de.pandaquests.myapplication;

import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.ArrayList;

public class ExampleAdapter extends RecyclerView.Adapter<ExampleAdapter.ExampleViewHolder> {
    private ArrayList<ExampleItem> mExampleList;

    public static class ExampleViewHolder extends RecyclerView.ViewHolder {
        public TextView mTextViewLine1;
        public TextView mTextViewLine2;

        public ExampleViewHolder(View itemView) {
            super(itemView);
            mTextViewLine1 = itemView.findViewById(R.id.textview_line1);
            mTextViewLine2 = itemView.findViewById(R.id.textview_line_2);
        }
    }

    public ExampleAdapter(ArrayList<ExampleItem> exampleList) {
        mExampleList = exampleList;
    }

    @Override
    public ExampleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.example_item, parent, false);
        ExampleViewHolder evh = new ExampleViewHolder(v);
        return evh;
    }

    @Override
    public void onBindViewHolder(ExampleViewHolder holder, int position) {
        ExampleItem currentItem = mExampleList.get(position);

        holder.mTextViewLine1.setText(currentItem.getLine1());
        holder.mTextViewLine2.setText(currentItem.getLine2());
    }

    @Override
    public int getItemCount() {
        return mExampleList.size();
    }
}

Now we only need our custom Object. Let's create "ExampleItem.java" file in your project folder and paste in the following code:

package de.pandaquests.myapplication;
public class ExampleItem {
    private String mLine1;
    private String mLine2;

    public ExampleItem(String line1, String line2) {
        mLine1 = line1;
        mLine2 = line2;
    }

    public String getLine1() {
        return mLine1;
    }

    public String getLine2() {
        return mLine2;
    }
}

We should now be set. Press on run and you should see a working sample app that saves custom data.

If you like it, then please share it with others.

You can download the app here from my gitHub and tweak it as you like:
https://github.com/pandaquests/AndroidSaveData

Use it as a base for your own projects. If you want, then tell me what projects you intend or have done with. I'm really curious to know. So long

Tweet