8
\$\begingroup\$

I am working on an Android application for reading NFC cards. I came to a point when I needed to design an abstract class to streamline the process of creating views for visualizing and editing various forms of data by subclassing the abstract class with views like BinaryView, HexView, StringView, et cetera.

I became aware that I wanted to use what I later discovered is named the "Back Stack", so I wrote up a small "testing" application project in Eclipse. developer.android.com kindly provided just what I needed; and after some research I was finally able to discover a reliable way of transmitting data to the child Activity during onCreate, and lastly a method for the parent Activity to accept data from the child Activity via all three finish() equivalents (the Action Bar "back" button, the previously hardware "back" button, and lastly a custom button within the child activity's view).

The following small files are the result of this morning's adventurous discovery:

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.tests"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="16"
        android:targetSdkVersion="23" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="app_label" >
        <activity
            android:name=".MainActivity"
            android:label="app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".ChildActivity"
            android:parentActivityName=".MainActivity" >
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value=".MainActivity" />
        </activity>
    </application>

</manifest>

MainActivity.java

package com.example.tests;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;

public class MainActivity extends Activity {
    public static final String EXTRA_LABEL = "extra";
    private EditText text;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LinearLayout layout = new LinearLayout(this);
        layout.setOrientation(LinearLayout.VERTICAL);
        text = new EditText(this);
        text.setText("initial value");
        Button button = new Button(this);
        button.setText("call");
        final MainActivity parent = this;
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Activity child = new ChildActivity();
                Intent intent = Intents.addStackActivity(parent, child);
                intent.putExtra(EXTRA_LABEL, text.getText().toString());
                startActivityForResult(intent, ChildActivity.EXTRA_LABEL_CODE);
            }
        });
        layout.addView(button);
        layout.addView(text);
        this.setContentView(layout);
    }
    @Override public void onActivityResult(int requestCode, int resultCode, final Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == ChildActivity.EXTRA_LABEL_CODE) {
             runOnUiThread(new Runnable() {
                 @Override public void run() {
                     text.setText(data.getStringExtra(ChildActivity.EXTRA_LABEL));
                 }
             });
        }
    }
}

Intents.java

package com.example.tests;

import android.app.Activity;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;

public class Intents {
    public static Intent addStackActivity(Context parent, Activity activity) {
        int id = 1;

        Intent resultIntent = new Intent(parent, activity.getClass());
        TaskStackBuilder stackBuilder = TaskStackBuilder.create(parent);
        // Adds the back stack
        stackBuilder.addParentStack(activity.getClass());
        // Adds the Intent to the top of the stack
        stackBuilder.addNextIntent(resultIntent);
        // Gets a PendingIntent containing the entire back stack
        PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,
                PendingIntent.FLAG_UPDATE_CURRENT);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(
                parent);
        builder.setContentIntent(resultPendingIntent);
        NotificationManager mNotificationManager = (NotificationManager) parent
                .getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.notify(id, builder.build());
        return resultIntent;
    }
}

ChildActivity.java

package com.example.tests;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;

public class ChildActivity extends Activity {
    public static final String EXTRA_LABEL = "mwahahaha";
    public static final int EXTRA_LABEL_CODE = 12345678;
    private EditText text;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent intent = getIntent();
        String data = intent.getExtras().getString(MainActivity.EXTRA_LABEL);
        LinearLayout layout = new LinearLayout(this);
        layout.setOrientation(LinearLayout.VERTICAL);
        text = new EditText(this);
        text.setText(data);
        Button button = new Button(this);
        button.setText("return");
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                setTextResult();
                finish();
            }
        });
        layout.addView(button);
        layout.addView(text);
        this.setContentView(layout);
        // setContentView(R.layout.activity_main);
    }

    private void setTextResult() {
        Intent intent = new Intent();
        intent.putExtra(ChildActivity.EXTRA_LABEL, text.getText().toString());
        this.setResult(ChildActivity.EXTRA_LABEL_CODE, intent);
    }

    @Override public void onBackPressed() {
        setTextResult();
        finish();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home:
            onBackPressed();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

Before I port this code back into my project, how can it be improved?

\$\endgroup\$

1 Answer 1

3
+100
\$\begingroup\$

Style

You're a little inconsistent about how you're placing your @Overrides. Sometimes, you place them like this:

@Override
public void foo( ... ) {
    ...
}

Other times, you place them like this:

@Override public void foo( ... ) {
    ...
}

Personally, I'd prefer the top version, but as long as you're being consistent, either style is probably okay.

The code contained in the file MainActivity.java suffers from a lack of blank lines, and whitespace in general, which makes it very hard to read. I took the liberty of adding a few blank lines, and some whitespace in there, and this was the result:

...

public class MainActivity extends Activity {
    public static final String EXTRA_LABEL = "extra";
    private EditText text;

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

        LinearLayout layout = new LinearLayout(this);
        layout.setOrientation(LinearLayout.VERTICAL);

        text = new EditText(this);
        text.setText("initial value");

        Button button = new Button(this);
        button.setText("call");

        final MainActivity parent = this;
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Activity child = new ChildActivity();
                Intent intent = Intents.addStackActivity(parent, child);
                intent.putExtra(EXTRA_LABEL, text.getText().toString());
                startActivityForResult(intent, ChildActivity.EXTRA_LABEL_CODE);
            }
        });

        layout.addView(button);
        layout.addView(text);
        this.setContentView(layout);
    }

    @Override 
    public void onActivityResult(int requestCode, int resultCode, final Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == ChildActivity.EXTRA_LABEL_CODE) {
             runOnUiThread(new Runnable() {
                 @Override 
                 public void run() {
                     text.setText(data.getStringExtra(ChildActivity.EXTRA_LABEL));
                 }
             });
        }
    }
}

There are more blank lines, but it's overall, much easier to read.


Nitpicks

This line here:

int id = 1;

Should be either of these two things:

  1. A constant.
  2. A function parameter.

I'd personally go with the function parameter, as it's a pain to go and change a constant variable to a different value each time you need it to have a different value, but if id is always going to be equal to 1, then it should probably just look like this:

final int ID = 1;

If there's anything else you want me to review, just mention it in the comments, and I'll see what I can do.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.