android - 如何在 Android 中使用后台线程保存文件

标签 android multithreading android-asynctask xmlserializer

我目前已经创建了一个函数,该函数使用 XmlSerializer 从对象创建 XML 文件。我一直在研究使用不同形式的多线程,以便在 GUI 仍然可用并且仍在更新的同时将文件保存在后台。我考虑过使用 AsyncTask 来执行此操作,但不确定什么是实现它的最佳方法。任何人都可以帮我解决这个问题,在此先感谢您。

这是我目前的代码:

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();
    }
}

最佳答案

AsyncTask 类实现了一种最佳实践模式,用于将耗时(但短暂)的处理移至后台线程并同步回 UI 线程,以便在完成时将更新应用于 UI。请注意,此类任务不会在 Activity 重新启动后持续存在,因此例如,如果您的设备方向发生变化,这些任务将被取消。

但是,如果您不需要将 UI 更新作为后台任务的一部分(这里似乎就是这种情况),则只需使用普通的 Thread 类,它的实现要简单得多(编辑:为从后台线程更新 UI):

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();

请注意,这种类型的线程确实会在 Activity 重新启动时持续存在,因此它通常应该运行到完成。

要将此作为 AsyncTask(如果需要更新 UI,这可能是更好的选择),可以通过以下方式实现相同的目的:

在您的 Activity 中,创建异步类的实例并执行。

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

在您的 Activity 中将 AsyncTask 子类化为私有(private)类

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
 }
}

关于android - 如何在 Android 中使用后台线程保存文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20067730/

相关文章:

android - 用安卓手机在空中画画

android - 在网络浏览器中打开链接

Android - 进度对话框不显示在 AsyncTask 中

java - 无法通过蓝牙设备地址在android中创建套接字

java - 使用 KOTLIN android studio 进行 JUnit 测试 [基本计算器]

android - AVD 无法在 Android Studio 上运行

c++ - 使用共享指针来自另一个线程的纯虚拟调用

multithreading - QThread 在主线程上休眠

java - 线程完成时 Log4j 追加到日志文件

java - Java调用常量时出错