简体   繁体   English

在后台更新ListView?

[英]Update a ListView in background?

I have a Fragment that contain a ListView with Adapters. 我有一个包含带有适配器的ListView的片段。 I want when replace this Fragment the listview continue changing on background. 我想要替换此片段时,列表视图在后台继续更改。 To do it I create a method with a TimerTask inside a AsyncTask, because I want the ListView change to each 10 seconds. 为此,我创建了一个在AsyncTask内包含TimerTask的方法,因为我希望ListView每10秒更改一次。 If the Fragment that contain the ListView is visible without replace its works fine, but if I make replace isn't works and throws an exception NullPointerException. 如果包含ListView的Fragment在不进行替换的情况下可见,则可以正常工作,但是如果我进行替换,则无法正常工作,并抛出NullPointerException异常。

How can I solve it ? 我该如何解决?

I'm trying this. 我正在尝试这个。

Fragment 分段

public class JogosAbertosFrag extends Fragment implements View.OnClickListener, AdapterView.OnItemClickListener {
    private ImageButton btPerfil;
    private Intent intentPerfil;
    private ListView lvJogosFinalizados;
    private ListView lvJogosAndamento;
    protected ProgressDialog progressDialog;
    private JogosListAdapter jogosListAdapterAndamento, jogosListAdapterFechado;
    private TextView tvPontuacao;
    private List<Batalha> listBatalhaAberto, listBatalhaFechado;

    //clock
    private Timer timer;
    private TimerTask timerTask;



    @Override
    public void onCreate(Bundle savedInstanceState) {    
        super.onCreate(savedInstanceState);
        ((CustomDrawerLayout)getActivity()).getSupportActionBar().show();

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.jogosabertos, container, false);

        lvJogosFinalizados  = (ListView)rootView.findViewById(R.id.lvJogosFinalizados);
        lvJogosFinalizados.setOnItemClickListener(this);
        lvJogosAndamento    = (ListView)rootView.findViewById(R.id.lvJogosAndamento);
        lvJogosAndamento.setOnItemClickListener(this);

        tvPontuacao = (TextView)rootView.findViewById(R.id.tvPontuacao);
        tvPontuacao.setText(BatalhaConfigs.USUARIO_PONTUACAO);


        btPerfil = (ImageButton)rootView.findViewById(R.id.btPerfil);
        btPerfil.setOnClickListener(this);

        return rootView;
    }


    @Override
    public void onActivityCreated(Bundle savedInstanceState) {        
            super.onActivityCreated(savedInstanceState);
            clockTask();
    }

    /**  */
    private void getAllBattles(){
        ApplicationController app = new BatalhaDAO().getAllBattles(new BatalhaAdapter(){
            @Override
            public void getAllBattlesOpened(List<Batalha> list) {
                if(!list.isEmpty()){
                    listBatalhaAberto = list;
                    if(jogosListAdapterAndamento == null){
                        jogosListAdapterAndamento = new JogosListAdapter(getView().getContext(), listBatalhaAberto);
                        lvJogosAndamento.setAdapter(jogosListAdapterAndamento);
                    }else{
                        jogosListAdapterAndamento.changeList(listBatalhaAberto);
                    }                   
                }               
            }

            @Override
            public void getAllBattlesClosed(List<Batalha> list) {
                if(!list.isEmpty()){
                    listBatalhaFechado = list;
                    if(jogosListAdapterFechado == null){
                        jogosListAdapterFechado = new JogosListAdapter(getView().getContext(), listBatalhaFechado);
                        lvJogosFinalizados.setAdapter(jogosListAdapterFechado);
                    }else{
                        jogosListAdapterFechado.changeList(listBatalhaFechado);
                    }
                }                
            }

        });
        CustomVolleySingleton.getInstance(getView().getContext()).addToRequestQueue(app);
    }



    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        FragmentTransaction ft;
        Fragment frag;
        if(parent == lvJogosAndamento){
            Batalha batalha = listBatalhaAberto.get(position);          
            Bundle params = new Bundle();
            params.putSerializable("infoBatalha", batalha);
            frag = new JogarComOponenteFrag();
            frag.setArguments(params);
            ft = getFragmentManager().beginTransaction();
            ft.replace(R.id.fl, frag);
            ft.addToBackStack("back");
            ft.commit();        

        }else if(parent == lvJogosFinalizados){

        }
    }


    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub

    }

    /** timer para atualizar o adapter */
    private void clockTask(){
        new AsyncTask<String, Void, String>() {
            @Override
            protected String doInBackground(String... params) {             
                timer = new Timer();
                timerTask = new TimerTask() {

                    @Override
                    public void run() {
                        getActivity().runOnUiThread(new Runnable() {                    
                            @Override
                            public void run() {
                                tvPontuacao.setText(BatalhaConfigs.USUARIO_PONTUACAO);
                                getAllBattles();
                            }
                        });                             
                    }
                };
                timer.scheduleAtFixedRate(timerTask, 100, 10000);
                return "execute";
            }

        }.execute("execute");

    }


    @Override
    public void onStop() {
        super.onStop();     
        CustomVolleySingleton.getInstance(getView().getContext()).cancelPendingRequests(CustomVolleySingleton.TAG);
    }

}

ListAdapter ListAdapter

public class JogosListAdapter extends BaseAdapter {
    private List<Batalha> lista;
    private Context context;    

    public JogosListAdapter(Context context, List<Batalha> list){
        this.context = context;
        this.lista = list;
    }

    @Override
    public int getCount() {
        return lista.size();
    }

    @Override
    public Object getItem(int position) {
        return lista.get(position);
    }

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

    public void changeList(List<Batalha> lista){
        this.lista = lista;
        notifyDataSetChanged();
    }

    @Override
    public View getView(int position, View view, ViewGroup parent) {
        View layout;
        if (view == null){
            LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            layout = inflater.inflate(R.layout.jogos_list_adapter, parent, false);
        }else{
            layout = view;
        }
      return layout;
}

Exception 例外

 FATAL EXCEPTION: main
 java.lang.NullPointerException
    at br.com.mypackage.myapp.frags.JogosAbertosFrag.getAllBattles(JogosAbertosFrag.java:113)
    at br.com.mypackage.myapp.frags.JogosAbertosFrag.access$12(JogosAbertosFrag.java:84)
    at br.com.mypackage.myapp.frags.JogosAbertosFrag$2$1$1.run(JogosAbertosFrag.java:170)
    at android.os.Handler.handleCallback(Handler.java:730)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:176)
    at android.app.ActivityThread.main(ActivityThread.java:5419)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:525)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
    at dalvik.system.NativeStart.main(Native Method)

Exception Lines 例外行

113 has -> CustomVolleySingleton.getInstance(getView().getContext()).addToRequestQueue(app);
84  has ->  private void getAllBattles(){}
170 close -> private void clockTask(){

First of All, you need to assign the Anonymous Inner Type AsyncTask class to a class variable. 首先,您需要将Anonymous Inner Type AsyncTask类分配给一个类变量。 Before doing that you need to create a nested AsyncTask class within your Activity. 在此之前,您需要在Activity中创建一个嵌套的AsyncTask类。

Your extended AsyncTask class should look something like this : 您扩展的AsyncTask类应如下所示:

public class MyContinousAsyncTask extends AsyncTask<String, Void, String>() {
        @Override
        protected String doInBackground(String... params) {             
            timer = new Timer();
            timerTask = new TimerTask() {

                @Override
                public void run() {
                    getActivity().runOnUiThread(new Runnable() {                    
                        @Override
                        public void run() {
                            tvPontuacao.setText(BatalhaConfigs.USUARIO_PONTUACAO);
                            getAllBattles();
                        }
                    });                             
                }
            };
            timer.scheduleAtFixedRate(timerTask, 100, 10000);
            return "execute";
        }

    }

Then you need to declare a class variable of this Class in your Activity: 然后,您需要在Activity中声明此类的类变量:

private MyContinousAsyncTask myContinouslyRunningAsyncTask;

now after doing the above, just modify your clockTask() method like this: 现在,完成上述操作后,只需像这样修改您的clockTask()方法即可:

/** timer para atualizar o adapter */
private void clockTask(){
 myContinouslyRunningAsyncTask = new MyContinousAsyncTask();
 myContinouslyRunningAsyncTask.execute("execute");

}

now you should stop this AsyncTask on the onPause() Event of your Fragment, other wise you will be getting NPE because of accessing the de-allocated UI Components. 现在您应该在Fragment的onPause()事件上停止此AsyncTask,否则,由于访问已取消分配的UI组件,您将获得NPE

The code should look like this: 该代码应如下所示:

 @Override

 protected void onPause() {
    // TODO Auto-generated method stub
    super.onPause();
    if(myContinouslyRunningAsyncTask != null)
    {
      myContinouslyRunningAsyncTask.cancel();
    }

    if(timer != null)
    {
     timer.cancel();
     timer.purge();
    }
}

To make your code further efficient, you should not call the clockTask(); 为了使您的代码更加高效,您不应调用clockTask(); in onActivityCreated(..) method, but in onResume() method, like this: onActivityCreated(..)方法中,但是在onResume()方法中,如下所示:

@Override
protected void onResume() {
    // TODO Auto-generated method stub
    super.onResume();
    clockTask();
 }

I hope this helps. 我希望这有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM