使用AsyncTask进行Android listview最佳实践

时间:2015-08-02 09:28:36

标签: android listview android-asynctask

我想开发一个Android应用程序,它向服务器询问一些数据,并在ListView中显示这些数据。 目前,我使用的是单个Activity(没有片段),布局非常简单:它由ImageView,EditText和ListView组成。单击ImageView时,它将获取EditText的内容并将其作为新项目发送到服务器,并自动更新Listview(在调用添加操作后调用对象的方法)。 我创建了一个AsyncTask类,其中包含Activity中的进度对话框,后台作业从服务器获取对象,然后将它们分配给List(封闭类的成员)。 通过这种做法,我面临很多问题:列表显示正确但非常缓慢!当我按下ImageView时,AsyncTask在添加新项目之后被调用来完成它的工作,但问题是它的对话框永远不会解散。 我的问题是Android中这种情况的最佳做法是什么?什么是最好的设计模式?我应该使用片段吗?我应该如何管理我的主题?

UDATE:

这里是AsyncTask:

public void refreshPostList() {
    try {
        BusInfo.getInstance().register(UserDetailsActivity.this); // register the Bus to recieve results.
    } catch (Exception e) {
       Log.d("My application says : ;) ", "Erro registering " + e);
    }

    pd = ProgressDialog.show(this, "Please Wait", "Loading");
    new ExprienceEdit(this, "hello").execute();
    }

这个方法回复了帖子:

  public void newPost(View v) {
    ParseObject post = new ParseObject("Post");
    post.put("content", editText.getText().toString());
    post.saveInBackground();
    refreshPostList();
     }

     <ImageView
                android:id="@+id/new_post"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:onClick="newPost"
                android:padding="10dp"
                android:src="@drawable/ic_action_post" />

按钮及其方法

my_sequence.NEXTVAL

3 个答案:

答案 0 :(得分:0)

处理asynctasks的最佳方法是使用otto:

Otto实际上是一个单一的公共汽车:请参阅这个网站http://square.github.io/otto/

任何一段代码都可以帮助您解决所面临的问题。

我准备回答任何问题。

BusInfo.getInstance.register(ActivityName.this) // register the Bus to recieve results.

pd = ProgressDialog.show(ActivityName.this, "Please Wait", "Loading");
new ExperienceEdit(getApplicationContext(), "hello").execute(); //async task to be executed let us say on button click

现在体验编辑是:

public class ExperienceEdit extends AsyncTask<Void, Void, String> {

Context c;
String id;

public ExperienceEdit(Context c, String id\) {
    this.c = c;
    this.id = id;
}

@Override
protected String doInBackground(Void... voids) {
    //right the call to back here
}

@Override
public void onPostExecute(String result) {
    try {
        BusInfo.getInstance().post(new ExperienceEditResult(result));
    } catch (Exception e) {
        e.printStackTrace();
    }
}
 }

发布后的结果是在以下活动中订阅的:

@Subscribe
public void onAsyncTaskResult(EditExperienceResult result) {
    if (pd != null)
        pd.dismiss();
    object = result.getResult();
    if (object != null) {
        if (object.equals("success")) {
            Toast.makeText(getApplicationContext(), "Success", Toast.LENGTH_SHORT).show();
            onBackPressed();
        } else Toast.makeText(getApplicationContext(), "Failure", Toast.LENGTH_SHORT).show();
    } else
        Toast.makeText(getApplicationContext(), "Please try again later", Toast.LENGTH_SHORT).show();
}

ExperienceEditResult恰好是一个字符串(你可以随心所欲):

public class ExperienceEditResult {
private String result;

public ExperienceEditResult(String result) {
    this.result = result;
}

public String getResult() {
    return result;
}
}

BusInfo类是:

public class BusInfo {
private static final Bus BUS = new Bus();

public static Bus getInstance() {
    return BUS;
}
}

不要忘记取消注册活动的总线onDestroy:BusInfo.getInstance()。unregister(ActivityName.this);

如果您还希望阻止进度对话框始终显示,因为有时它会因为双击按钮而显示两次,请添加:if(pd!= null&amp;&amp; pd.isShowing()){ Log.v(“pd显示”,“显示”); } else {pd = ProgressDialgue.show ...}

答案 1 :(得分:0)

关于未被驳回的进度对话框: mProgressDialog对话框在哪里声明?我建议你把它移到RemoteDataTask中。 (我猜你在某种程度上压倒了当前的实例,因此解雇不起作用)

关于列表的慢速刷新,请发布适配器代码。您应该正确地回收视图,并且不应每次都重新创建适配器,而是设置数据并调用notifyDataSetChanged,以便listView将使用新数据回收视图。请查看有关正确回收视图的答案:https://stackoverflow.com/a/6923513/348378

修改1 我还建议这样做以防止有多个refreshTasks:

public void refreshPostList() {
    if(dataTask == null) {
       dataTask = new RemoteDataTask(this).execute();
    }
}

@Override
protected void onPostExecute(Void result) {
    // you stuff
    dataTask = null;
}

您还可以考虑取消当前任务并根据所需行为开始新任务。

答案 2 :(得分:0)

您应该将ProgressDialog传递给AsyncTask类构造函数,并且在任何想要使用AsyncTask类的类中(在您的情况下为RemoteDataTask),您应该实例化进度对话框并将第二个参数传递给RemoteDataTask以控制特定自定义类的可见性。 也许这有帮助。