【问题标题】:Code doesn't execute HttpResponse for second time when called twice调用两次时,代码不会第二次执行 HttpResponse
【发布时间】:2014-12-15 01:28:21
【问题描述】:

我正在做的应用程序调用了两次相同的方法,第二次调用该方法时它不会执行带有 HttResponse 的行。

这里是一切开始的 AsyncTask:

private class FetchSubjectsTask extends AsyncTask<String, Void, List<Subject>> {
    private ProgressDialog pd;
    @Override
    protected List<Subject> doInBackground(String... params) {

        List<Subject> subjects = null;
        try {
            subjects = api.getMySubjects(params[0]);

        } catch (Exception e) {
            e.printStackTrace();
        }
            return subjects; 
    }

    @Override
    protected void onPostExecute(List<Subject> result) {

        printSubjects(result);

        if (pd != null) {
            pd.dismiss();
        }
    }
}

然后我通过 getMySubjects 方法获取主题:

public List<Subject> getMySubjects(String username) {
    List<Subject> subjects = new ArrayList<Subject>();
    java.lang.reflect.Type arrayListType = new TypeToken<ArrayList<Subject>>() {
    }.getType();
    String url = BASE_URL_VM + "users/" + username + "/subjects";
    HttpClient httpClient = WebServiceUtils.getHttpClient();
    try {
        System.out.println("inside try");
        HttpResponse response = httpClient.execute(new HttpGet(url));
        System.out.println("response executed");
        HttpEntity entity = response.getEntity();
        Reader reader = new InputStreamReader(entity.getContent());
        subjects = gson.fromJson(reader, arrayListType);
    } catch (Exception e) {

    }
    System.out.println("Array lenght " +subjects.size());
    return subjects;
}

这是第一次 HttpResponse 执行,我得到“响应执行”和“数组长度 2”,这是用户(用户名)在数据库中的主题数。

问题是在 onPostExecute 中我调用 printSubjects 方法,即:

private void printSubjects(List<Subject> subjects){
    adapter = new SubjectAdapter(this,(ArrayList<Subject>)subjects, (String) getIntent().getExtras().get("username"));
    setListAdapter(adapter);
    adapter.notifyDataSetChanged();
}

这调用了在 ListView 中打印主题的 SubjectAdapter:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub
    ViewHolder viewHolder = null;
    if (convertView == null) {  
    convertView = inflater.inflate(R.layout.subject_detail, null);
    viewHolder = new ViewHolder();
    viewHolder.tvsubject = (TextView) convertView
            .findViewById(R.id.tvsubject);

    boolean match = api.checkMySubjects(username, data.get(position).getId());

    Button addButton = (Button) convertView.findViewById(R.id.bAdd);
    if(match){
        addButton.setText("Delete");
    }else{
        addButton.setText("Add");
    }

    String content = data.get(position).getName();
    viewHolder.tvsubject.setText(content);
    }
    return convertView;
}

private static class ViewHolder {
    TextView tvsubject;
    TextView tvauthor;
}

这里我调用了 checkMySubjects 方法,它再次调用 getMySubjects 进行比较。

public boolean checkMySubjects(String username, String id) {
    List<Subject> mySubjects = getMySubjects(username);
    boolean match = false;
    for (Subject s1 : mySubjects) {
        if (s1.getId().equals(id)) {
            match = true;
        }
    }
    return match;
}

但是现在 getMySubjects 方法直到“响应执行”才到达,并且数组长度为 0。它只显示“内部尝试”。 为什么?我使用相同的 URL 调用相同的方法,但第一次我得到了数组中的 2 个主题,第二次我什么也没得到,因为 HttResponse 没有执行。

谢谢!

【问题讨论】:

    标签: android http response httpresponse


    【解决方案1】:

    很难说发生了什么,但我想指出我认为这是错误的。首先,让我们说明getMySubjects 执行网络操作的事实,现在,您第一次调用它时,它是在UI 线程以外的线程上的AsyncTask 内调用的。这很好

    然后你在onPostExecute 中调用printSubjects,它会用结果填充ListView...

    private void printSubjects(List<Subject> subjects){
        adapter = new SubjectAdapter(this,(ArrayList<Subject>)subjects, (String) getIntent().getExtras().get("username"));
        setListAdapter(adapter);
        adapter.notifyDataSetChanged();
    }
    

    现在,问题在于适配器的getView 实现。更具体的在这里...

    boolean match = api.checkMySubjects(username, data.get(position).getId());
    

    这非常糟糕,因为每次为 ListView 项目充气时,您都会在 UI 线程上建立网络连接,所以如果您有十个项目,您将建立十次网络连接(加上每次您向上滚动和/或列表中)。

    此外,如果您尝试在 UI 线程上建立网络连接,Android 会发出 FATAL 异常。你甚至没有注意到,因为你没有对这个例外做任何事情......

    try {
            System.out.println("inside try");
            HttpResponse response = httpClient.execute(new HttpGet(url));
            System.out.println("response executed");
            HttpEntity entity = response.getEntity();
            Reader reader = new InputStreamReader(entity.getContent());
            subjects = gson.fromJson(reader, arrayListType);
        } catch (Exception e) {
    
        }
    

    catch 块是空的,如果您将其打印到 LogCat,您将看到详细信息

    建议

    1. 不要在 UI 线程上建立网络连接...你不能
    2. 在 getView 上,不要为每次迭代都建立网络连接,而是在设置 ListView 之前急切地将数据加载到内存中

    同样,有问题的代码行是......

    boolean match = api.checkMySubjects(username, data.get(position).getId());
    

    在getView

    【讨论】:

    • 感谢您的回复!我明白你在说什么,但我不知道如何解决这个问题。我应该在 AsyncTask 的后台找到一种方法吗?
    • @Alhar 没关系。不幸的是,我无法在这里为您编写完整的解决方案。但是,是的,AsyncTask、Thread 或任何不在 UI 线程上运行的东西。在ListView 上设置适配器之前检索您需要的所有数据,而不是在getView 方法中获取数据
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多