如何在android中的活动加载之间维护ListView状态

时间:2013-08-03 21:49:26

标签: android listview

我正在我的活动中进行一些后台处理,并有一个显示进度的ListView。我用

更新了listView
adapter.notifyDataSetChanged(); 

但是,当我离开活动然后返回时,后台进程仍在运行,但列表视图未更新。这可能是因为它是一个新对象,而不是之前的对象。如何在活动加载之间维护列表视图对象?

这是我的活动。我认为问题在于,下载用于绑定以显示更新的“适配器”变量在活动的onCreate方法中重新创建,并且下载最初绑定的“适配器”变量不再存在于活动中

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;


import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.model.ProgressEvent;
import com.amazonaws.services.s3.model.ProgressListener;
import com.amazonaws.services.s3.transfer.TransferManager;

//import com.amazonaws.auth.AWSCredentials;
//import com.amazonaws.auth.BasicAWSCredentials;


public class VideosActivity extends Activity {

    ListView           video_list;             
    CustomList         adapter;
    File               storage_dir;
    SharedPreferences  completed_downloads;      //http://developer.android.com/guide/topics/data/data-storage.html
    SharedPreferences  downloaded_data;          //maps position to percent downloaded
    SharedPreferences  queue;                    //holds which fiiles are awaiting download
    String             images[];                 //holds references to all thumnails for vids

    String             volume;                   //something like vol1 or vol2
    String             s3_dir;                   //the directory after the boucket that the files are stored in (do not add first slash)
    String             s3_bucket                 = "com--apps";
    Handler            handler                   = new Handler(); //'tunnel' through whci other threads communicate with main thread


    Map<String, String[][]> video_config         = new HashMap<String, String[][]>(); //holds info about video thumbs and filenames for all apps
    ArrayList<String>       arr_videos           = new ArrayList<String>();  //holds video names
    DownloadQueue           queue_manager        = new DownloadQueue();



    @Override
    public void onCreate(Bundle savedInstanceState) {

        Log.v("dev", "onCreateCalled");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        volume               = getPackageName().split("\\.")[2]; //something like vol1 or vol2
        s3_dir               = "android/" + volume + "/"; //the directory after the boucket that the files are stored in (do not add first slash)
        completed_downloads  = getSharedPreferences("completed_downloads", 0); 
        downloaded_data      = getSharedPreferences("downloaded_data", 0); 
        queue                = getSharedPreferences("queue", 0); 
        storage_dir          = getApplicationContext().getExternalFilesDir(null);        //private to app, removed with uninstall
        adapter              = new CustomList(this, R.layout.customlist, arr_videos);
        video_list           = (ListView)findViewById(R.id.list);

        video_list.setAdapter(adapter);         //set adapter that specifies list contents
        ensureStorageDirExists( storage_dir );  //make sure storage dir exists
        set_video_data();                       //store vid dat in array

        ensure_connection_or_warn();
    }

    public boolean ensure_connection_or_warn()
    {
        if(have_connection())
        {
          return true;
        }
        else
        {
          Toast.makeText(this, "No Internet connection", Toast.LENGTH_LONG).show();
          return false;
        }
    }
    protected void ensureStorageDirExists( File dir ) 
    {
      if (!dir.exists())
      {
        dir.mkdirs();
      }
    }

    public void set_video_data() 
    {


      config_video_data(); //run config

      images     = video_config.get(getPackageName())[0]; //set images

      for (String name : video_config.get(getPackageName())[1] ) { //set video info, this should be streamlined but is due to legacy code and my crap Java skills, consider doing like this: http://developer.android.com/guide/topics/resources/more-resources.html#TypedArray
        arr_videos.add(name);
      }

    }


    public SharedPreferences stored_vals()
    {

        return PreferenceManager.getDefaultSharedPreferences(this);
    }

    public boolean have_connection()
    {
      ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

      if(cm.getActiveNetworkInfo()!=null && cm.getActiveNetworkInfo().isConnected() && cm.getActiveNetworkInfo().isAvailable())
      {
        Log.v("dev", "have internet connection");
        return true;
      }
      else
      {
        Log.v("dev", "No internet connection");
        return false;
      }

    }





    public class DownloadQueue
    {
      protected void process()
      {
        if (queue.size() > 0 && queue.get(0).download_status == "queued") //this is meant to force one download at a time
        {
          queue.get(0).start();
          adapter.notifyDataSetChanged();
        }
      }
      protected void add(Integer position)
      {
        queue.edit.putInt(position+"");
        d.download_status = "queued";
        adapter.notifyDataSetChanged();
      }
      protected boolean position_is_queued(Integer position)
      {
        for (Download d : queue ) {
          if(d.position == position)
          {
            return true;
          }
        }

        return false;
      }
      protected void remove(Download d)
      {
        queue.remove(d);
        adapter.notifyDataSetChanged();
      }
    }

    public class CustomList extends ArrayAdapter<String>
    {
        View view;
        int position;
        Button btn;

        public CustomList(Context context, int layout_id, ArrayList<String> objects) 
        {
            super(context, layout_id, objects);
        }

        @Override
        public View getView(final int position, View convertView, ViewGroup view_group) 
        {
          set_view(convertView);

          this.position          = position;
          TextView  text_view    = (TextView)  view.findViewById(R.id.name);
          ImageView image        = (ImageView) view.findViewById(R.id.img);
          btn                    = (Button)    view.findViewById(R.id.play);

          prepare_btn();

          text_view.setText( list_text() );
          image.setImageResource( 
            getResources().getIdentifier(images[position], "drawable", getPackageName())
          );

          return view;
        }

        public String list_text()
        {
          String s = arr_videos.get( position ).replace("_", " ").replace(".m4v", "");
          s        = s.substring(2, s.length());
          return s;
        }

        public void set_view(View convertView)
        {
          if(convertView == null) 
          {
            LayoutInflater inflater                      = getLayoutInflater();
            view                                         = inflater.inflate(R.layout.customlist, null);
          } 
          else 
          {
            view = convertView;
          }
        }

        public Boolean is_downloaded()
        {
          return completed_downloads.getBoolean(position + "", false);
        }

        public void prepare_btn()
        {
          btn.setTag((Integer) position);

          if(is_downloaded() == true)
          {
            btn.setText("Play ");
            btn.setEnabled(true);

            btn.setOnClickListener( new OnClickListener() 
            {
              public void onClick(View btn) 
              {
                int    position   = (Integer) btn.getTag();
                Intent i          = new Intent(VideosActivity.this, PlayVideoActivity.class);
                String video_path = storage_dir + "/" + arr_videos.get(position);

                Log.v("video_path", video_path);

                i.putExtra("video_path", video_path);
                startActivity(i);
              }
            });
          }
          else if( downloaded_data.contains(position+"") )  //it it's currently being downloaded
          {
            btn.setText(downloaded_data.getInt(position+"", 0) + "%");
            btn.setEnabled(false);
          }
          else if( queue_manager.position_is_queued(position) ) //it's in the queue
          {
            btn.setText("Queued");
            btn.setEnabled(false);
          }
          else
          {
            btn.setText("Download");
            btn.setEnabled(true);

            btn.setOnClickListener( new OnClickListener() 
            {
              public void onClick(View btn) 
              {
                int position = (Integer) btn.getTag();
                btn.setEnabled(false);

                queue_manager.add(position);
              }
            });
          }
        }

    }


    public class Download
    {

       File              new_video_file;
       int               position;
       String            download_status;
       com.amazonaws.services.s3.transfer.Download  download;

       protected void queue(int position) 
       {
          this.position                = position;
          queue_manager.add(this);
          queue_manager.process();

          //put this download in the queue
          //start downloading if it's the only one in the queue
       }
       protected void start() 
       {
          if(!ensure_connection_or_warn())
          {
            return;
          }

          this.download_status         = "started";
          this.new_video_file          = new File(storage_dir, arr_videos.get(position));                   //local file to be writtent to
          TransferManager tx           = new TransferManager(credentials);
          //http://stackoverflow.com/questions/6976317/android-http-connection-exception
          this.download                = tx.download(s3_bucket, s3_dir + arr_videos.get(position), new_video_file);


          download.addProgressListener(new ProgressListener() 
          {
            public void progressChanged(final ProgressEvent pe) 
            {
              handler.post( new Runnable() 
              {
                @Override
                public void run() 
                {
                  if ( pe.getEventCode() == ProgressEvent.COMPLETED_EVENT_CODE )
                  {
                    Download.this.onComplete();
                  }
                  else
                  {
                    Download.this.onProgressUpdate();
                  }
                }
              });
            }
          });
       }

       //protected void onProgressUpdate(Double progress)
       protected void onProgressUpdate()
       {
          this.download_status         = "downloading";
          Double progress = this.download.getProgress().getPercentTransfered();
          Integer percent  = progress.intValue();
          //Log.v("runnable", percent + "");

          downloaded_data.edit().putInt(position+"", percent).commit();


          adapter.notifyDataSetChanged();
       }
       protected void onComplete()
       {
          Log.v("dev", "download complete!!!");
          //downloaded_data.remove(position);

          this.download_status         = "complete";

          completed_downloads.edit().putBoolean(position + "", true).commit();

          queue_manager.remove(this);
          queue_manager.process();

          adapter.notifyDataSetChanged();


         // this.download.abort();
       }
    }


}

1 个答案:

答案 0 :(得分:0)

不完全确定在后台处理过程中会发生什么,以及ListView状态是什么意思,但我的建议是:

尝试以下方法:

@Override
protected void onResume() {
    super.onResume();

    yourAdapter.clear();
    yourAdapter.addAll(yourData);  // API level [1..10] use for(..){ yourAdapter.add(yourData.get(index)) }
    yourAdapter.notifyDataSetChanged();
}

原因:

适配器保留所有元素的副本,因此当您调用notifyDataSetChanged时,它会检查自己的元素副本