Question

I have a class which implements Parcelable, and could not implement Serializable because it contains some basic Android classes that I can not modify.

Some of the objects in this class are for example Location and PendingIntent (which are all conveniently Parcelable).

My problem is saving this information between the instances of my main Activity.

Currently, I'm holding a static reference to this class, which works well. But I assume that when I re-install the app, and probably when updates will come around, I won't be able to trust that this static member won't be re-initialized.

I tried to write this Parcelable to a file, but using marshall() is not always working (I'm getting Binder can't be marshalled error).

How can I safely save this information?

Thanks

Was it helpful?

Solution 2

I use a StateControl class to handle reading/writing to disc:

    public class StateControl {

    Context mContext;

    Thread worker;
    WriteObjectToFile writer;

    // StateControl Constructor 
    public StateControl(Context context) {
        mContext = context; 

        // Construct a writer to hold and save the data
        writer = new WriteObjectToFile();

        // Construct a worker thread to handle the writer
        worker = new Thread(writer);

    }// end of StateControl constructor




    // Method to save the global data
    public void saveObjectData(Object object, String key) {

        if (object == null){
            // I had a different action here
        } else {

            // Write the data to disc
            writer.setParams(new WriteParams(object, key));         
            worker.run();

        }

    }// end of saveGlobalData method


    // Method to read the Global Data
    public Object readObjectData(String key){

        Object returnData = (Object) readObjectFromFile(key);

        if (returnData == null){        
            // I had a different action here
        } else {    
            return returnData;
        }

    }// end of readGlobalData method


    // Method to erase the Global data
    public void clearObjectData(String key){

        writer.setParams(new WriteParams(null, key));       
        worker.run();

    }// end of clearGlobalData method   

    private class WriteObjectToFile implements Runnable {

        WriteParams params;

        public void setParams(WriteParams params) {
            this.params = params;
        }

        public void run() {         
            writeObjectToFile(params.getObject(), params.getFilename());                
        }

        private boolean writeObjectToFile(Object object, String filename) {

            boolean success = true;

                ObjectOutputStream objectOut = null;
                try {

                    FileOutputStream fileOut = mContext.openFileOutput(filename, Activity.MODE_PRIVATE);
                    objectOut = new ObjectOutputStream(fileOut);
                    objectOut.writeObject(object);
                    fileOut.getFD().sync();

                } catch (IOException e) {
                    success = false;
                    e.printStackTrace();
                } finally {
                    if (objectOut != null) {
                        try {
                            objectOut.close();
                        } catch (IOException e) {
                            // do nothing
                        }

                    }// end of if 
                }// End of try/catch/finally block

            return success;
        }

    }// end of writeObjectToFile method


    private Object readObjectFromFile(String filename) {

        ObjectInputStream objectIn = null;
        Object object = null;
        try {

            FileInputStream fileIn = mContext.getApplicationContext().openFileInput(filename);
            objectIn = new ObjectInputStream(fileIn);
            object = objectIn.readObject();

        } catch (FileNotFoundException e) {
            // Do nothing
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (objectIn != null) {
                try {
                    objectIn.close();
                } catch (IOException e) {
                    // do nowt
                }
            }
        }

        return object;
    }


    private static class WriteParams {

        Object object;
        String filename;

        public WriteParams(Object object, String filename) {
            super();
            this.object = object;
            this.filename = filename;
        }

        public Object getObject() {
            return object;
        }

        public String getFilename() {
            return filename;
        }

    }

}

Then invoke the public methods to kick off the writing/reading. For this version, I also having it taking place in a separate thread, but you could modify that if you needed to.

OTHER TIPS

Using static in your example leads to memory leaks and is not a good way to do anything.

I suggest using static only in 3 cases:

  1. static final String or int - constants
  2. on inner classes (so that they don't contain reference to outer class)
  3. on util or in some cases (like CustomFragment.newInstance) factory methods

The question is why would you want to persist PendingIntent? Its usecase is for inter-process-communication.

Binder

Most developers will not implement this class directly, instead using the aidl tool to describe the desired interface, having it generate the appropriate Binder subclass.

from the official documentation

Do you need to store the Binder object with the rest of your object? Maybe you can save your object without the Binder instance, and re-create the Binder object with aidl after you restore the object

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top