如何动态刷新 ListView? [复制]

Posted

技术标签:

【中文标题】如何动态刷新 ListView? [复制]【英文标题】:How to refresh a ListView dynamically? [duplicate] 【发布时间】:2013-09-16 03:03:38 【问题描述】:

我正在尝试实现刷新动态值的 ListAdapter。如果我不需要从互联网连接中获取值(我的情况),这不是一个大问题。

为此,我在适配器中实现了一个 AsyncTask 内部类,但屏幕值的更新不起作用。所有过程都执行没有错误,但屏幕上的信息没有改变。

下面是关于我的代码的一些cmets:

我的 getView 方法被执行并调用 ConsultaPrevisaoBackGround (我的 AsyncTask) 来查询来自互联网的值,他在 getView 方法的末尾执行。

在 AsyncTask 类中,我从 Internet 获取值,并在 onPostExecuteMethod 中调用方法来刷新我的持有者(用于封装小部件的类)。它工作正常(正在运行),但不会反映在屏幕信息中。其实有时候更新屏幕有时候不更新。

我的疑惑是:

1 - 我的策略正确吗?如果是,错误在哪里? 2 - 我可以做些什么来执行这个过程一次,而不是每次用户滚动屏幕时都执行?

我在这方面工作了很长时间,但找不到解决方案...求助!!

package br.com.teste.adapters;

import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;

import android.content.Context;
import android.os.AsyncTask;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;
import br.com.teste.beans.horarios.Estimativa;
import br.com.teste.beans.horarios.Previsao;
import br.com.teste.beans.linhas.Linha;
import br.com.teste.R;
import br.com.teste.util.PrevisaoUtil;

public class ListaLinhasAdapter extends BaseAdapter 
private Context context;
private List<Linha> linhas;
private String pontoId;
private LayoutInflater inflater;
private ViewHolder holder;
private String idLinha;
private Previsao p;

public ListaLinhasAdapter(Context context, List<Linha> listaLinhas,
        String pontoID) 
    this.context = context;
    this.linhas = listaLinhas;
    this.pontoId = pontoID;
    this.inflater = LayoutInflater.from(context);


@Override
public int getCount() 
    return linhas.size();


@Override
public Object getItem(int position) 
    return linhas.get(position);


@Override
public long getItemId(int position) 
    return position;


@Override
public View getView(int position, View view, ViewGroup parent) 
    // Recupera o estado da posição atual
    Linha linha = linhas.get(position);

    if (view == null) 
        view = inflater.inflate(R.layout.listadadoslinhas, null);
        holder = new ViewHolder(context);
        // Número da linha
        holder.txtIdLinha = (TextView) view.findViewById(R.id.txtIdLinha);
        // Nome da linha
        holder.txtNomeLinha = (TextView) view
                .findViewById(R.id.txtNomeLinha);

        // Seta campo de informação sem parada
        holder.txtMsgSemParada = (TextView) view
                .findViewById(R.id.msgSemParada);

        // seta layouts de previsão
        holder.llLinha1 = (LinearLayout) view
                .findViewById(R.id.linearPrevisoes1);
        holder.llLinha2 = (LinearLayout) view
                .findViewById(R.id.linearPrevisoes2);
        holder.llLinha3 = (LinearLayout) view
                .findViewById(R.id.linearPrevisoes3);

        // Seta campos de previsão
        holder.txtPrev1 = (TextView) view.findViewById(R.id.txtPrev1);
        holder.txtPrev2 = (TextView) view.findViewById(R.id.txtPrev2);
        holder.txtPrev3 = (TextView) view.findViewById(R.id.txtPrev3);
        holder.txtPrev4 = (TextView) view.findViewById(R.id.txtPrev4);
        holder.txtPrev5 = (TextView) view.findViewById(R.id.txtPrev5);
        holder.txtPrev6 = (TextView) view.findViewById(R.id.txtPrev5);

        view.setTag(holder);
     else 
        holder = (ViewHolder) view.getTag();
        holder.reset();
    

    String lin = linha.getLinha().trim();
    StringTokenizer stk = new StringTokenizer(lin, "-");

    // Número da linha
    idLinha = stk.nextToken();
    holder.txtIdLinha.setText(idLinha);

    // Nome da linha
    holder.txtNomeLinha.setText(stk.nextToken());

    new ConsultaPrevisaoBackGround().execute("");

    return view;


static class ViewHolder 
    Context context;
    TextView txtIdLinha;
    TextView txtNomeLinha;
    TextView txtMsgSemParada;

    LinearLayout llLinha1;
    LinearLayout llLinha2;
    LinearLayout llLinha3;

    TextView txtPrev1;
    TextView txtPrev2;
    TextView txtPrev3;
    TextView txtPrev4;
    TextView txtPrev5;
    TextView txtPrev6;

    public ViewHolder(Context cont) 
        this.context = cont;
    

    public void reset() 
        txtIdLinha.setText(null);
        txtNomeLinha.setText(null);
        limpaPrevisoes();
    

    //Clear fields
    private void limpaPrevisoes() 
        llLinha1.setVisibility(View.GONE);
        llLinha2.setVisibility(View.GONE);
        llLinha3.setVisibility(View.GONE);
        txtMsgSemParada.setVisibility(View.GONE);

        txtPrev1.setText(null);
        txtPrev2.setText(null);
        txtPrev3.setText(null);
        txtPrev4.setText(null);
        txtPrev5.setText(null);
        txtPrev6.setText(null);
    

    //Show message error in textview
    public void showError() 
        showMsg(context.getResources().getString(R.string.msgErroPrevisao));
    

    public void showMsg(String msg) 
        limpaPrevisoes();
        txtMsgSemParada.setText(msg);
    

    public void fillPrevisao(Previsao p) 
        Collections.sort(p.getPonto());

        if (p.getPonto().size() > 6) 
            // get only first 6 occurs
            for (int i = 6; i < p.getPonto().size(); i++)
                p.getPonto().remove(i);
        

        int cont = 1;
        for (Estimativa estimativa : p.getPonto()) 
            setPrevisao(cont, estimativa, p);
            cont++;
        

        if (p.getPonto().size() <= 2) 
            llLinha2.setVisibility(View.GONE);
            llLinha3.setVisibility(View.GONE);
        

        if ((p.getPonto().size() > 2) && (p.getPonto().size() <= 4))
            llLinha3.setVisibility(View.GONE);

    

    // Preenche o campo referente à estimativa
    private void setPrevisao(int id, Estimativa estimativa,
            Previsao previsao) 

        switch (id) 
        case 1:
            txtPrev1.setText(getPrevisaoFormatada(previsao, estimativa));
            setBackGroundColor(estimativa, txtPrev1);
            break;
        case 2:
            txtPrev2.setText(getPrevisaoFormatada(previsao, estimativa));
            setBackGroundColor(estimativa, txtPrev2);
            break;
        case 3:
            txtPrev3.setText(getPrevisaoFormatada(previsao, estimativa));
            setBackGroundColor(estimativa, txtPrev3);
            break;
        case 4:
            txtPrev4.setText(getPrevisaoFormatada(previsao, estimativa));
            setBackGroundColor(estimativa, txtPrev4);
            break;
        case 5:
            txtPrev5.setText(getPrevisaoFormatada(previsao, estimativa));
            setBackGroundColor(estimativa, txtPrev5);
            break;
        case 6:
            txtPrev6.setText(getPrevisaoFormatada(previsao, estimativa));
            setBackGroundColor(estimativa, txtPrev6);
            break;
        default:
            break;
        

    

    private String getPrevisaoFormatada(Previsao previsao,
            Estimativa estimativa) 
        String horaStr;
        String minutoStr;
        long horaAtual = Long.parseLong(previsao.getHorarioAtual());
        long segundos = (estimativa.getHorarioPacote() - horaAtual) / 1000;
        int semanas = (int) Math.floor(segundos / 604800);
        segundos -= semanas * 604800;
        int dias = (int) Math.floor(segundos / 86400);
        segundos -= dias * 86400;
        int horas = (int) Math.floor(segundos / 3600);
        segundos -= horas * 3600;
        int minutos = (int) Math.floor(segundos / 60);
        segundos -= minutos * 60;

        minutos += 1;

        if (horas < 10)
            horaStr = "0" + horas;
        else
            horaStr = String.valueOf(horas);

        if (minutos < 10)
            minutoStr = "0" + minutos;
        else
            minutoStr = String.valueOf(minutos);

        String tempo;
        if (horas > 0)
            tempo = horaStr + "h " + minutoStr + "min";
        else
            tempo = minutoStr + "min";

        SimpleDateFormat spf = new SimpleDateFormat("HH:mm:ss");
        tempo = tempo + " às "
                + spf.format(estimativa.getHorarioEstimado());
        return tempo;
    

    private void setBackGroundColor(Estimativa estimativa, TextView txtView) 
        // Imagem a ser exibida
        switch (estimativa.getStatus()) 
        case 0:
            txtView.setBackgroundColor(context.getResources().getColor(
                    R.color.previsaoVerde));
            break;
        case 1:
            txtView.setBackgroundColor(context.getResources().getColor(
                    R.color.previsaoLaranja));
            break;
        case 2:
            txtView.setBackgroundColor(context.getResources().getColor(
                    R.color.previsaoVermelha));
            break;
        default:
            break;
        
    


private class ConsultaPrevisaoBackGround extends AsyncTask<String, Void, String> 

    @Override
    protected String doInBackground(String... params) 
            try 
                PrevisaoUtil pUtil = new PrevisaoUtil(pontoId.trim(), idLinha.trim(),
                        context);
                p = pUtil.getPrevisao();
             catch (Exception e) 
                return "error";
            
        return "Executed";
    

    @Override
    protected void onPostExecute(String result) 
        if(result.equals("error"))
        
            holder.showError();
            return;
        
        if ((p.getErro() != null) && (p.getErro().trim().length() > 0))
            holder.showMsg(p.getErro());

        if ((p.getPonto() == null) || (p.getPonto().size() == 0))
            holder.showMsg(context.getResources().getString(
                    R.string.msgSemPrevisao));

        holder.fillPrevisao(p);
    


对不起,大帖子,但信息多比信息少

更新

问题解决了,我从适配器中删除了 AsynkTask 内部类并放入了活动中。

【问题讨论】:

【参考方案1】:

如果您想刷新您的 ListView,请调用

 notifyDataSetChanged()

在您的适配器上。

也可以看看ListView.invalidateViews()

也看看这个问题和答案:How to refresh Android listview?

【讨论】:

不适合我,谢谢【参考方案2】:

覆盖 ConsultaPrevisaoBackGround

private class ConsultaPrevisaoBackGround extends AsyncTask<String, Void, String> 
    ViewHolder holder;
    public  ConsultaPrevisaoBackGround(ViewHolder holder)
        this.holder = holder;
    

使用 Holder 刷新 UI

【讨论】:

抱歉,我不明白这将如何解决问题。【参考方案3】:

抱歉这个比较容易理解

private class ConsultaPrevisaoBackGround extends AsyncTask<String, Void, String> 
    ViewHolder holder;
    public  ConsultaPrevisaoBackGround(ViewHolder holder)
        this.holder = holder;
    

@Override
protected String doInBackground(String... params) 
        try 
            PrevisaoUtil pUtil = new PrevisaoUtil(pontoId.trim(), idLinha.trim(),
                    context);
            p = pUtil.getPrevisao();
         catch (Exception e) 
            return "error";
        
    return "Executed";

【讨论】:

以上是关于如何动态刷新 ListView? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何动态刷新ListView的显示

【delphi】动态刷新listview,如果条目过多,会出问题,求解

Listview刷新不适用于动态

Android ListView动态刷新某项Item

android如何给listview添加动态加载数据

spring动态加载(刷新)配置文件 [复制链接]