0

我是否需要将此方法转换为一个类并扩展 AsyncTask 才能使用它?我在某处读到我不应该从 UI 线程运行 DB 操作?

如果是这样,我该怎么做呢?

这是代码ATM:

public void addNewContact() {
    HashMap<String, String> queryValuesMap = new HashMap<String, String>();
    queryValuesMap.put("userName", userName);
    queryValuesMap.put("userEmail", userEmail);
    queryValuesMap.put("userPassword", userPassword);
    queryValuesMap.put("userAvatar", userAvatar);
    queryValuesMap.put("userSex", userSex);
    dbTools.insertUser(queryValuesMap);
    dbTools.close();
}

它从我的提交按钮 onClick() 中调用。

我想我应该做的是:

private class AddNewContact extends AsyncTask <Void, Void, Void> {

            @Override
            protected Void doInBackground(Void... params) {
            try {
            HashMap<String, String> queryValuesMap = new HashMap<String, String>();
                queryValuesMap.put("userName", userName);
                queryValuesMap.put("userEmail", userEmail);
                queryValuesMap.put("userPassword", userPassword);
                queryValuesMap.put("userAvatar", userAvatar);
                queryValuesMap.put("userSex", userSex);
                dbTools.insertUser(queryValuesMap);
                dbTools.close();
            } catch (Exception e) {}
        return null;
    }
}

然后在提交按钮 onClick() 中的 AddNewContact.execute()。

这是正确的吗?

编辑:这是在接受答案下方的讨论中实施后的工作代码:

在 onClick 中:

        AddNewUserParams addNewUserParams = new AddNewUserParams();
        addNewUserParams.userName = this.userName;
        addNewUserParams.userEmail = this.userEmail;
        addNewUserParams.userPassword = this.userPassword;
        addNewUserParams.userAvatar = this.userAvatar;
        addNewUserParams.userSex = this.userSex;

        new AddNewContact().execute(addNewUserParams);

这是嵌套类:

private class AddNewUserParams {
    String userName;
    String userEmail;
    String userPassword;
    String userAvatar;
    String userSex;
}
private class AddNewContact extends AsyncTask <AddNewUserParams, Void, Void> {

    @Override
    protected Void doInBackground(AddNewUserParams... params) {
        try {
        HashMap<String, String> queryValuesMap = new HashMap<String, String>();
            queryValuesMap.put("userName", params[0].userName);
            queryValuesMap.put("userEmail", params[0].userEmail);
            queryValuesMap.put("userPassword", params[0].userPassword);
            queryValuesMap.put("userAvatar", params[0].userAvatar);
            queryValuesMap.put("userSex", params[0].userSex);
            dbTools.insertUser(queryValuesMap);
            dbTools.close();
        } catch (Exception e) {
            toastMaker.toast(net.asdqwe.activities.Signup.this, configurationz.ERROR_MESSAGES_SIGNUP_USER_NOT_CREATED, configurationz, Toast.LENGTH_LONG);
        }
return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        Intent signupSuccessHome = new Intent(getApplicationContext(), Home.class);
        signupSuccessHome.putExtra(EXTRA_MESSAGE, userEmail);
        startActivity(signupSuccessHome);
        super.onPostExecute(result);
    }
}
4

3 回答 3

1

除非您在 UI 线程中执行长操作,否则您永远不应该从 UI 线程运行 DB 操作正确的。这样做的主要原因是不减慢 UI 线程。当您在 DB 中插入一个非常小的值时,您可以毫无顾虑地使用您的代码,但要养成使用 Async Task 将数据插入/检索到数据库中的习惯,以免减慢 UI 线程的速度。

于 2013-10-06T10:53:56.710 回答
1

大多数情况下,是的。

所有视图回调(onClick 等)都在主线程上执行。您应该确保在主线程上也不会执行任何涉及磁盘或网络的操作。特别是,数据库访问、网络、文件读/写和长时间运行的计算都应该在不同的线程上进行(例如,通过使用AsyncTask)。

不过,你做错了两件事。

1)您没有传入操作参数(用户名、密码等)。您可以将Params模板参数(第一个)设置为String,这将为您提供Void doInBackground(String.. params). 这样,操作的想法就与您目前可能插入的特定值分开了。

2)你在压制失败。那个 try-empty-catch-all 块是一个非常非常糟糕的做法,你应该避免它。您可以将 Result 类型更改为 Boolean,然后在onPostExecute.

于 2013-10-06T10:56:18.463 回答
1

从文档:

理想情况下,AsyncTasks 应该用于短操作(最多几秒钟)。AsyncTask 可以正确和轻松地使用 UI 线程。此类允许在 UI 线程上执行后台操作并发布结果,而无需操作线程和/或处理程序。 这里

在网络任务等简单的事情中,数据库处理应该在单独的线程而不是主 UI 线程中处理。

至于你的问题:是的,使用 Aysnc 任务

你上面写的几乎是正确的:

第一个参数需要是 String 以传入一个可以访问的字符串数组,protected Void doInBackground(String... strings) {或者strings[0] = userName etc...在之前创建 HashMap 并将 hashmap 作为第一个参数传入。拥有空的 catch 块也是不好的做法,您至少应该记录一个错误。

添加代码

@Override
        protected Void doInBackground(String... params) {

        try {
        HashMap<String, String> queryValuesMap = new HashMap<String, String>();
            queryValuesMap.put("userName", params[0]);
            queryValuesMap.put("userEmail", params[1]);
            queryValuesMap.put("userPassword", params[2]);
            queryValuesMap.put("userAvatar", params[3]);
            queryValuesMap.put("userSex", params[4]);
            dbTools.insertUser(queryValuesMap);
            dbTools.close();
        } catch (Exception e) {}
    return null;

你会这样称呼你的新人Async Class

new AddNewContact().execute(userName, email, etc...);

如果您想向progress dialog用户显示 a ,您可以像这样覆盖 onPreExecute 和 onPostExecute :

@Override
    protected void onPreExecute() {
        progressDialog.show();
        progressDialog.setCancelable(false);
    }

@Override
    protected void onPostExecute(JSONObject json) {
           progressDialog.dismiss();
    }
于 2013-10-06T10:59:16.773 回答