简体   繁体   中英

Accessing resources in a static final array in a utility class

I have a utility class for diagnostics (run time info, warning and error events) that defines the codes, severity levels, and human-readable messages for all possible diagnostics. There is also a DiagHolder that holds the information for the diag that was selected from the array and accessors for that data.

I am refactoring away from hardcoded strings in the Java in order to use R.string for localization of the text that describes the diagnostic.

    public class Diagnostic {

    // Debugging
    private static final boolean D = true;  // debugging?
    private static final String TAG = "Diagnostic";
    static Context mContext;
    DiagHolder mDiagHolder;
    String mTimestamp;


    public enum DIAG_TYPE{
        INFO,
        WARNING,
        ERROR
    }

    public enum DIAG_CODE {
        SYSTEM_ONLINE,
        SELF_TEST_COMPLETE,
        GPS_SYNCH,
        BATTERY_50,
        BATTERY_25,
        UNEXPECTED_RESET,
        UNKNOWN_ERROR
    }

    static final DiagHolder[] Diags = {

            //new DiagHolder("System powered up.", DIAG_CODE.SYSTEM_ONLINE, DIAG_TYPE.INFO),
            new DiagHolder(mContext.getResources().getString(R.string.SYSTEM_ONLINE), DIAG_CODE.SYSTEM_ONLINE, DIAG_TYPE.INFO),
            new DiagHolder("Self test complete. No issues.", DIAG_CODE.SELF_TEST_COMPLETE, DIAG_TYPE.INFO),
            new DiagHolder("GPS synchronized.", DIAG_CODE.GPS_SYNCH, DIAG_TYPE.INFO),
            new DiagHolder("Battery less than 50 percent.", DIAG_CODE.BATTERY_50, DIAG_TYPE.WARNING),
            new DiagHolder("Battery less than 25 percent.", DIAG_CODE.BATTERY_25, DIAG_TYPE.WARNING),
            new DiagHolder("Unexpected reset occured.", DIAG_CODE.UNEXPECTED_RESET, DIAG_TYPE.ERROR),
            new DiagHolder("Unknown error.", DIAG_CODE.UNKNOWN_ERROR, DIAG_TYPE.ERROR),
    };

    public static class DiagHolder {
        private String mmDescription;
        private DIAG_CODE mmCode;
        private DIAG_TYPE mmType;

        DiagHolder(String description, DIAG_CODE code, DIAG_TYPE type)
        {
            this.mmDescription = description;
            this.mmCode = code;
            this.mmType = type;
        }
    }


    Diagnostic(DIAG_CODE code, String timestamp, Context context) {
        if (code.ordinal() >= 0 && code.ordinal() < Diags.length) {
            this.mDiagHolder = Diags[code.ordinal()];
            this.mTimestamp = timestamp;
            this.mContext = context;
        }
        else {
            this.mDiagHolder = new DiagHolder("Invalid diagnostic.", DIAG_CODE.UNKNOWN_ERROR, DIAG_TYPE.ERROR);
        }

    }

    public String getDescription()
    {
        return this.mDiagHolder.mmDescription;
    }

    public DIAG_CODE getCode()
    {
        return this.mDiagHolder.mmCode;
    }

    public DIAG_TYPE getType()
    {
        return this.mDiagHolder.mmType;
    }

    public String getmTimestamp()
    {
        return mTimestamp;
    }
}

As you can see above, I have commented out the first diag with the table and replaced it with a line that accesses R.string. I accessed R by passing context to the Diagnostic from the Activity.This will not work, however, since it generates an NPE on the getResources() call.

Below id the call from the activity. I have added a dummy diagnostic for display:

public class ViewDiagnosticsActivity extends AppCompatActivity {
...
private void buildDiagnosticList()
{
    Diagnostic p = new Diagnostic(Diagnostic.DIAG_CODE.SYSTEM_ONLINE, "26OCT16 1439:10.76", this.getApplicationContext());
    diagnostics.add(p);
}

}

Is there a better pattern for doing this?

Since Diags is a static field, it will be initialized just after the DiagHolder class is loaded. At that time, context is probably not initialized yet, presuming that classes are loaded much before contexts are set up. So, using a context in static initializations is dangerous.

In this case, in DiagHolder class you can make a method like

public static void init(Context context);

and initialize your Diags field in it.

The NullPointerException is quite clear: ''context'' is never defined.

Pay attention that your ''DiagHolder'' is a static inner class, and therefore it can be instatiated without an instance of the enclosing class, but in that case it does not have access to instance members of the enclosing class (because they don't exist!)

here, i have declared a static Context, before accessing that DiagHolder[],must initialize that static context.

package com.example.prince.practice;

import android.content.Context;

public class Diagnostic {
public static Context context;

public enum DIAG_TYPE {
    INFO, ERROR
}

public enum DIAG_CODE {
    SYSTEM_ONLINE, SYSTEM_OFFLINE
}

public static class DiagHolder {
    private String mmDescription;
    private DIAG_CODE mmCode;
    private DIAG_TYPE mmType;

    DiagHolder(String description, DIAG_CODE code, DIAG_TYPE type) {
        this.mmDescription = description;
        this.mmCode = code;
        this.mmType = type;
    }

    static final DiagHolder[] Diags = {
            //new DiagHolder("System powered up.", DIAG_CODE.SYSTEM_ONLINE, DIAG_TYPE.INFO),
            new DiagHolder(context.getResources().getString(R.string.SYSTEM_ONLIN), DIAG_CODE.SYSTEM_ONLINE, DIAG_TYPE.INFO)
    };
}

}

use from activity, like this:

    Diagnostic.context = this;
    Diagnostic.DiagHolder[] holders = Diagnostic.DiagHolder.Diags;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM