Question

I currently have created a function that uses XmlSerializer to create an XML file from objects. I have been researching about using different forms of multi threading in order to save the file in the background whilst the GUI is still usable and is still updating. I looked at using AsyncTask to do this, but am not to sure on what is the best way to implement it. Please can anyone help me with this and thank you in advance.

Here is the code that I have so far:

private String fileName;
private DataObjects dataObjects;

public SetCachedValuesFile() 
{

}

public void setFileName(String refFileName)
{
    fileName = refFileName;
}

public void setDataObjects(DataObjects refDataObjects)
{
    dataObjects = refDataObjects;
}

public String getFileName()
{
    return fileName;
}

public DataObjects getDataObjects()
{
    return dataObjects;
}

public void updateValues()
{
    ArrayList<DataObject> arrayListDataObject = dataObjects.getDataObjects();
    try 
    {
        /* Creates a new file and its directory. */
        File directory = new File(Environment.getExternalStorageDirectory() + "/XML_FILES/");
        directory.mkdirs();
        File newFile = new File(directory, fileName + ".xml");
        FileOutputStream fos = new FileOutputStream(newFile);

        /* Creates a new XML serializer which creates the structure of the XML file. */
        XmlSerializer serializer = Xml.newSerializer();
        serializer.setOutput(fos, "UTF-8");
        serializer.startDocument(null, true);
        serializer.startTag("", "CachedValues");
        for(DataObject dataObject : arrayListDataObject)
        {
            if(dataObject.getClass().equals(StringDataObject.class))
            {
                StringDataObject stringDataObject = (StringDataObject) dataObject;
                String address = HexFunctions.toString(stringDataObject.getAddress());
                String value = stringDataObject.getValue();

                serializer.startTag("", "DataObject");
                serializer.startTag("", "Address");
                serializer.text(address);
                serializer.endTag("", "Address");
                serializer.startTag("", "Value");
                serializer.text(value);
                serializer.endTag("", "Value");
                serializer.endTag("", "DataObject");

                System.out.println("String data object added to file.");
            }
            else if(dataObject.getClass().equals(IntDataObject.class))
            {
                IntDataObject intDataObject = (IntDataObject) dataObject;
                String address = HexFunctions.toString(intDataObject.getAddress());
                String value = Integer.toString(intDataObject.getValue());

                serializer.startTag("", "DataObject");
                serializer.startTag("", "Address");
                serializer.text(address);
                serializer.endTag("", "Address");
                serializer.startTag("", "Value");
                serializer.text(value);
                serializer.endTag("", "Value");
                serializer.endTag("", "DataObject");

                System.out.println("Int data object added to file.");
            }
            else if(dataObject.getClass().equals(FloatDataObject.class))
            {
                FloatDataObject floatDataObject = (FloatDataObject) dataObject;
                String address = HexFunctions.toString(floatDataObject.getAddress());
                String value = Float.toString(floatDataObject.getValue());

                serializer.startTag("", "DataObject");
                serializer.startTag("", "Address");
                serializer.text(address);
                serializer.endTag("", "Address");
                serializer.startTag("", "Value");
                serializer.text(value);
                serializer.endTag("", "Value");
                serializer.endTag("", "DataObject");

                System.out.println("Float data object added to file.");
            }
            else if(dataObject.getClass().equals(DoubleDataObject.class))
            {
                DoubleDataObject doubleDataObject = (DoubleDataObject) dataObject;
                String address = HexFunctions.toString(doubleDataObject.getAddress());
                String value = Double.toString(doubleDataObject.getValue());

                serializer.startTag("", "DataObject");
                serializer.startTag("", "Address");
                serializer.text(address);
                serializer.endTag("", "Address");
                serializer.startTag("", "Value");
                serializer.text(value);
                serializer.endTag("", "Value");
                serializer.endTag("", "DataObject");

                System.out.println("Double data object added to file.");
            }
        }
        serializer.endTag("", "CachedValues");
        serializer.endDocument();
        serializer.flush();
        fos.close();

        System.out.println("File created");
        System.out.println("File name: " + newFile.getAbsolutePath());
    } 
    catch (IllegalArgumentException e) 
    {
        e.printStackTrace();
    } 
    catch (IllegalStateException e) 
    {
        e.printStackTrace();
    }
    catch (IOException e) 
    {
        e.printStackTrace();
    }
}
Was it helpful?

Solution

The AsyncTask class implements a best practice pattern for moving time consuming (but short lived) processing to a background thread and synchronising back to the UI thread, to apply updates to the UI, when complete. Note that such tasks do not persist across Activity restarts so for example will be cancelled if the orientation of your device changes.

However, if you don't need to update the UI as part of your background task (which appears to be the case here), then just use the normal Thread class which is much simpler to implement (edit: code added for updating the UI from a background thread):

Handler handler = new Handler();  //Optional. Define as a variable in your activity.

Runnable r = new Runnable()
{
    @Override
    public void run()
    {
        // your code here
        handler.post(new Runnable()  //If you want to update the UI, queue the code on the UI thread
        {
            public void run()
            {
                //Code to update the UI 
            }
        });
    }
};

Thread t = new Thread(r);
t.start();

Note that this type of threading does persist across activity restarts so it should usually run to completion.

To do this as an AsyncTask (which may be a better choice if the UI needs to be updated) the same thing can be achieved by:

In your activity, create an instance of your Async class and execute.

SaveData save = new SaveData();
save.execute();

Subclass AsyncTask as a private class within your activity

private class SaveData extends AsyncTask<String, Void, Boolean>{

@Override
protected Boolean doInBackground(String... params) {
    // your background code here. Don't touch any UI components

    if(your code worked...)
        return true;                
    else
        return false;
}

protected void onPostExecute(Boolean result) {
     //This is run on the UI thread so you can do as you wish here
     if(result)
         Toast successful
     else
         Toast unsuccessful
 }
}

OTHER TIPS

One thing to add to NigelK's answer is that if you use the AsyncTask you can only use it once. So you cannot call it twice as follows:

SaveData save = new SaveData();
save.execute();
//Later
save.execute();

Instead, you would need to do something like:

SaveData save1 = new SaveData();
save1.execute();
//Later
SaveData save2 = new SaveData();
save2.execute();

Additionally, if you need to run the task repetitively, you may want to use a handler and call it in the runnable like this:

Handler handler = new Handler();
Runnable runnable = new Runnable() {
    public void run() {
        SaveData save = new SaveData();
        save.execute();       
    }
};
handler.postDelayed(runnable, 500);

See these links. AsyncTask Threading Rule - Can it really only be used once? Call asynctask in handler

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