HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Reducing repetitive Android code

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
coderepetitivereducingandroid

Problem

How can I reduce the amount of repetitive code in my Android app? A lot of the code seems to be doing the same thing twice. I think that there is a more compact way to do this.

What are some ways that I can reduce lines of code in this program?

Is there a better way that I could write this program? I think that I am taking more steps than necessary.

The code is for this app.

```
package com.kerseykyle.easyhash;

import java.security.MessageDigest;

import android.os.Build;
import android.os.Bundle;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {

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

Intent intent = getIntent();
String action = intent.getAction();
String type = intent.getType();

if (Intent.ACTION_SEND.equals(action) && type != null) {
if ("text/plain".equals(type)) {
handleSendText(intent); // Handle text being sent
}
}

EditText myTextBox = (EditText) findViewById(R.id.input);
myTextBox.setSingleLine(true);
myTextBox.addTextChangedListener(new TextWatcher() {

public void afterTextChanged(Editable s) {
}

public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void onTextChanged(CharSequence s, int start, int before,
int count) {

String md5hash = CreateHash(s.toString(), "MD5");
TextView md5 = (TextView) findV

Solution

This type of problem is conveniently solved with a Strategy Pattern. But, first things first:

  • you should search for efficient ways to convert bytes to hexadecimal-string values. This is a great solution I like....



  • Unless you have no choice (you are using Patterns/Matchers) you should always use StringBuilder instead of StringBuffer



  • The method CreateHash should not have a capital-letter to start with, it should rather be createHash



As for the Strategy Pattern.... In this case, you can create a class that listens for the text change, and updates the signature in the linked TextView. The same class listens for on-click on the TextView too. The class could have the signature

public abstract class HashDigestDisplay implements TextWatcher, OnClickListener {
    private final TextView view;
    private final MessageDigest digest;

    public HashDigestDisplay (TextView target, String digestName) throws NoSuchAlgorithmException {
        this.view = target;
        this.digest = MessageDigest.getInstance(digestName);
        this.view.setOnClickListener(this);
    }

    public void afterTextChanged(Editable s) {
    }

    public void beforeTextChanged(CharSequence s, int start, int count,
            int after) {
    }

    private String myDigest(String input) {
        digest.reset(); 
        byte[] hash = digest.digest(input.getBytes("UTF-8"));
        return bytesToHex(hash);
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public void onTextChanged(CharSequence s, int start, int before, int count) {
            view.setText(myDigest(s.toString()));
            view.setTextIsSelectable(true);
    }

    @Override
    public void onClick(View v) {
            // TODO Auto-generated method stub
            EditText myTextBox = (EditText) findViewById(R.id.input);
            String hash = myDigest(myTextBox.getText().toString());
            Intent sendIntent = new Intent();
            sendIntent.setAction(Intent.ACTION_SEND);
            sendIntent.putExtra(Intent.EXTRA_TEXT, hash);
            sendIntent.setType("text/plain");
            startActivity(sendIntent);

    }
}


You can see the pattern that is emerging above. Obviously there are issues in the onClick method, but this is from copy/pasting your code.

Now, what you do in your onCreate() setup method is simply:

myTextBox.addTextChangedListener(
    new HashDigestDisplay((TextView) findViewById(R.id.md5), "MD5"));
myTextBox.addTextChangedListener(
    new HashDigestDisplay((TextView) findViewById(R.id.sha1), "SHA-1"));
....


After that, the system should be self-managing.

You only have one copy of the code, and the only things different about it are the name of the Digest and the target of the TextView.

Code Snippets

public abstract class HashDigestDisplay implements TextWatcher, OnClickListener {
    private final TextView view;
    private final MessageDigest digest;

    public HashDigestDisplay (TextView target, String digestName) throws NoSuchAlgorithmException {
        this.view = target;
        this.digest = MessageDigest.getInstance(digestName);
        this.view.setOnClickListener(this);
    }

    public void afterTextChanged(Editable s) {
    }

    public void beforeTextChanged(CharSequence s, int start, int count,
            int after) {
    }

    private String myDigest(String input) {
        digest.reset(); 
        byte[] hash = digest.digest(input.getBytes("UTF-8"));
        return bytesToHex(hash);
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public void onTextChanged(CharSequence s, int start, int before, int count) {
            view.setText(myDigest(s.toString()));
            view.setTextIsSelectable(true);
    }

    @Override
    public void onClick(View v) {
            // TODO Auto-generated method stub
            EditText myTextBox = (EditText) findViewById(R.id.input);
            String hash = myDigest(myTextBox.getText().toString());
            Intent sendIntent = new Intent();
            sendIntent.setAction(Intent.ACTION_SEND);
            sendIntent.putExtra(Intent.EXTRA_TEXT, hash);
            sendIntent.setType("text/plain");
            startActivity(sendIntent);

    }
}
myTextBox.addTextChangedListener(
    new HashDigestDisplay((TextView) findViewById(R.id.md5), "MD5"));
myTextBox.addTextChangedListener(
    new HashDigestDisplay((TextView) findViewById(R.id.sha1), "SHA-1"));
....

Context

StackExchange Code Review Q#38132, answer score: 4

Revisions (0)

No revisions yet.