如何保存和还原滚动位置和ListView状态

时间:2015-03-18 05:28:25

标签: android listview file-upload android-viewholder

让我们看一下工作的屏幕截图,以便更好地理解问题

  1. 我已将上传第一个列表项的图片发送到服务器[: - Thumbnail 1.png],如下图所示:
  2. enter image description here

    1. 我上传了 myfile 文件夹下的图片,使用 Localhost
    2. enter image description here

      1. 当我向下滚动 ListView时,得到这个 - 这就是真正的痛苦,正如您所看到的Thumbnail 7,我没有点击它:
      2. enter image description here

        1. 再一次,我向上滚动 ListView,得到一些东西 - 这让我感到恼火,对Thumbnail 2同样如此,我没有碰到那个:
        2. enter image description here

          我认为that's enough向您解释,我想要做什么发生什么 我遇到了问题

          现在轮到让我知道解决方案,我该如何解决这个问题?

          一些说明:

          我已将第一个列表项的图像上传到服务器(根据我的要求,我将图像状态显示为"已上传"现在已禁用上传按钮)但是当我向下/向上滚动时listview它显示列表中的任何一个项目上传而不是我上传的那个(我注意到主要是那个可见的列表项)并重置最初上传到服务器的第一个列表项的状态...

          所以在这里我只想让我最初上传的那个特定的上传状态稳定...不是任何可见的项目(那些还没有上传)

          只是影响列表视图,服务器上没有任何事情发生(只获取一张我上传的图片)

          MainActivity.java: -

          public class MainActivity extends Activity  {
          
              static ListView lstView;
              private Handler handler = new Handler();;
          
              static List <String> ImageList;
              String strPath;     
          
              int position ;
          
              static File f;
              File newFile;
          
          
              static File[] files ;
              static File  file ;
          
              ViewHolder holder;
              View v ;        
          
              String fileName;    
          
              @Override
              public void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);      
          
              setContentView(R.layout.activity_main);
          
          
              /*** Get Images from SDCard ***/
              ImageList = getSD();
          
              // ListView and imageAdapter
              lstView = (ListView) findViewById(R.id.listView);
              lstView.setAdapter(new ImageAdapter(this));
          
              }
          
              private List <String> getSD()
              {
                  List <String> it = new ArrayList <String>();
                  File f = new File ("/mnt/sdcard/mydata/");
                  File[] files = f.listFiles ();
          
                  for (int i = 0; i <files.length; i++)
                  {
                      File  file = files[i];
                      Log.d("Count",file.getPath());
                      it.add (file.getPath());
                  }
                  return it;
              }   
          
              static class ViewHolder {
                  public ViewHolder(View convertView) {
                      // TODO Auto-generated constructor stub
                  }                
          
                  TextView textName;
                  ImageView thumbnail;
                  TextView textStatus;
                  Button btnUpload;            
          
              }  
          
               public class ImageAdapter extends BaseAdapter
                  {
                      public ImageAdapter(Context c)
                      {
          
                      }
          
                      public int getCount() {
                          // TODO Auto-generated method stub
                          return ImageList.size();
                      }
          
                      public Object getItem(int position) {
                          // TODO Auto-generated method stub
                          return position;
                      }
          
                      public long getItemId(int position) {
                          // TODO Auto-generated method stub
                          return position;
                      }
          
              public View getView(final int position, View convertView, ViewGroup parent) {
                  // Avoid unneccessary calls to findViewById() on each row, which is expensive!
          
                      holder = null;
          
                      if (convertView == null) {
                      convertView = getLayoutInflater().inflate(R.layout.adapter_main, null);
                      holder = new ViewHolder(convertView);
          
                      // Create a ViewHolder and store references to the children views
                      holder.textName = (TextView) convertView.findViewById(R.id.textName);
                      holder.thumbnail = (ImageView) convertView.findViewById(R.id.thumbnail);                
                      holder.btnUpload = (Button) convertView.findViewById(R.id.btnUpload);
                      holder.textStatus = (TextView) convertView.findViewById(R.id.textStatus);
          
                      // The tag can be any Object, this just happens to be the ViewHolder
                      convertView.setTag(holder);                
                      } else {                    
                      holder = (ViewHolder) convertView.getTag();             
                      }
          
                      strPath = ImageList.get(position).toString();
          
                      // Get File Name
                      fileName = strPath.substring( strPath.lastIndexOf('/')+1, strPath.length() );
                      file = new File(strPath);
                      @SuppressWarnings("unused")
                      long length = file.length();
                      holder.textName.setText(fileName);
          
          
                      final BitmapFactory.Options options = new BitmapFactory.Options();
          
                      Bitmap bm = BitmapFactory.decodeFile(strPath,options);
                      holder.thumbnail.setImageBitmap(bm);       
          
                      //btnUpload
                      holder.btnUpload.setOnClickListener(new View.OnClickListener() {
                      public void onClick(View v) {
                              // Upload                           
                              startUpload(position);
                          }
                      });
          
                      return convertView;
          
                  }   
              }
          
          
          
                      // Upload
          
                      public void startUpload(final int position) {      
          
                          Runnable runnable = new Runnable() {
          
                          public void run() {
          
                              handler.post(new Runnable() {
          
                          public void run() {
          
                              v = lstView.getChildAt(position - lstView.getFirstVisiblePosition());
                              holder = (ViewHolder) v.getTag();
                              holder.btnUpload.setEnabled(false);
          
                                  new UploadFileAsync().execute(String.valueOf(position));   
                                          }
                                      });
                                  }
                              };
                              new Thread(runnable).start();
                              }
          
                              // Async Upload
                              public class UploadFileAsync extends AsyncTask<String, Void, Void> {
          
                                  String resServer;
          
                              protected void onPreExecute() {
                                  super.onPreExecute();
                              }
          
                              @Override
                              protected Void doInBackground(String... params) {
                              // TODO Auto-generated method stub
                                  position = Integer.parseInt(params[0]);
          
                                  int bytesRead, bytesAvailable, bufferSize;
                                  byte[] buffer;
                                  int maxBufferSize = 1 * 1024 * 1024;
                                  int resCode = 0;
                                  String resMessage = "";
          
                                  String lineEnd = "\r\n";
                                  String twoHyphens = "--";
                                  String boundary =  "*****";
          
                                  // File Path
                                  String strSDPath = ImageList.get(position).toString();
          
                                  // Upload to PHP Script
                                  String strUrlServer = "http://10.0.2.2/uploadFile.php";
          
                                  try {
                                      /** Check file on SD Card ***/
                                      File file = new File(strSDPath);
                                      if(!file.exists())
                                      {   
                                          resServer = "{\"StatusID\":\"0\",\"Message\":\"Please check path on SD Card\"}";
                                          return null;
                                      }
          
                                  FileInputStream fileInputStream = new FileInputStream(new File(strSDPath));
          
                                  URL url = new URL(strUrlServer);
                                  HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                                      conn.setDoInput(true);
                                      conn.setDoOutput(true);
                                      conn.setUseCaches(false);
                                      conn.setRequestMethod("POST");
          
                                      conn.setRequestProperty("Connection", "Keep-Alive");
                                      conn.setRequestProperty("Content-Type",
                                              "multipart/form-data;boundary=" + boundary);
          
                                  DataOutputStream outputStream = new DataOutputStream(conn
                                          .getOutputStream());
                                      outputStream.writeBytes(twoHyphens + boundary + lineEnd);
                                      outputStream
                                      .writeBytes("Content-Disposition: form-data; name=\"filUpload\";filename=\""
                                              + strSDPath + "\"" + lineEnd);
                                      outputStream.writeBytes(lineEnd);
          
                                  bytesAvailable = fileInputStream.available();
                                  bufferSize = Math.min(bytesAvailable, maxBufferSize);
                                  buffer = new byte[bufferSize];
          
                                  // Read file
                                  bytesRead = fileInputStream.read(buffer, 0, bufferSize);
          
                                  while (bytesRead > 0) {
                                      outputStream.write(buffer, 0, bufferSize);
                                      bytesAvailable = fileInputStream.available();
                                      bufferSize = Math.min(bytesAvailable, maxBufferSize);
                                      bytesRead = fileInputStream.read(buffer, 0, bufferSize);
                                  }
          
                                  outputStream.writeBytes(lineEnd);
                                  outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
          
                                  // Response Code and  Message
                                  resCode = conn.getResponseCode();
                                      if(resCode == HttpURLConnection.HTTP_OK)
                                      {
                                          InputStream is = conn.getInputStream();
                                          ByteArrayOutputStream bos = new ByteArrayOutputStream();
          
                                  int read = 0;
                                  while ((read = is.read()) != -1) {
                                      bos.write(read);
                                  }
          
                                  byte[] result = bos.toByteArray();
                                      bos.close();
          
                                  resMessage = new String(result);
          
                                  }
          
                                  Log.d("resCode=",Integer.toString(resCode));
                                  Log.d("resMessage=",resMessage.toString());
          
                                  fileInputStream.close();
                                  outputStream.flush();
                                  outputStream.close();
          
                                  resServer = resMessage.toString();
          
          
                                  } catch (Exception ex) {
                                      ex.printStackTrace();
                                  }
          
                                  return null;
                                  }
          
                                  protected void onPostExecute(Void unused) {
                                      statusWhenFinish(position,resServer);
                                      }
          
                                  }
          
          
                              // When Upload Finish
                              @SuppressWarnings("unused")
                              protected void statusWhenFinish(int position, String resServer) {
          
          
                              /*** Default Value ***/
                              String strStatusID = "0" ;
                              String strError = "" ;
          
                              try {      
          
                              JSONObject c = new JSONObject(resServer);
                              strStatusID = c.getString("StatusID");
                              strError = c.getString("Message");
                              } catch (JSONException e) {
                              // TODO Auto-generated catch block
                              e.printStackTrace();
                              }                                                                  
          
                              // prepare Status
                              if(strStatusID.equals("0"))
                              {                         
                                  // When update Failed
                                 holder.textStatus.setText("Failed");
                                 holder.btnUpload.setEnabled(true);
                              }
                              else
                              {
                                  holder.textStatus.setText("Uploaded");  
                                  holder.btnUpload.setEnabled(false);
                              }
          
                      }
          
          }
          

3 个答案:

答案 0 :(得分:1)

介绍如下结构:

/**
 * Introduce a class with below attributes to hold a state of each row in single
 * element
 * 
 */
public class MyData {
    /* Image url or path of image in single row */
    private String images;

    /* anme of image in single row */
    private String name;

    /* status ID of image in single row */
    private String statusID;

    /* message of image in single row */
    private String message;

    // Generate getters and setter
    public String getImages() {
        return images;
    }

    public void setImages(String images) {
        this.images = images;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getStatusID() {
        return statusID;
    }

    public void setStatusID(String statusID) {
        this.statusID = statusID;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

}

添加了适当的注释以理解代码。

// MyDataList是arrylist ArrayList(),你需要在构造函数中初始化这个数据结构

  public View getView(int position, View convertView, ViewGroup parent) {

    MyData fields = MyDataList.get(position);
}

修改:

我已经编辑了上面发布的代码,请看下面的代码我如何使用MyData来设置状态

package com.example.trial;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class MainActivity extends Activity {

    static ListView lstView;
    private Handler handler = new Handler();;
    static List<MyData> ImageList;
    String strPath;
    int position;
    File newFile;
    ViewHolder holder;
    View v;
    String fileName;
    ImageAdapter mAdapter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        /*** Get Images from SDCard ***/
        ImageList = getSD();
        // ListView and imageAdapter
        lstView = (ListView) findViewById(R.id.listView);
        mAdapter = new ImageAdapter(this);
        lstView.setAdapter(mAdapter);

    }

    private List<MyData> getSD() {
        List<MyData> it = new ArrayList<MyData>();
        String root_sd = Environment.getExternalStorageDirectory().toString();
        File f = new File(root_sd + "/Download");
        File[] files = f.listFiles();
        for (int i = 0; i < files.length; i++) {
            File file = files[i];
            Log.d("Count", file.getPath());
            MyData data = new MyData();
            data.setImages(file.getPath());
            data.setStatusEnable(true);
            it.add(data);
        }
        return it;
    }

    static class ViewHolder {
        public ViewHolder(View convertView) {
            // TODO Auto-generated constructor stub
        }

        TextView textName;
        ImageView thumbnail;
        TextView textStatus;
        Button btnUpload;

    }

    public class ImageAdapter extends BaseAdapter {
        public ImageAdapter(Context c) {

        }

        public int getCount() {
            // TODO Auto-generated method stub
            return ImageList.size();
        }

        public Object getItem(int position) {
            // TODO Auto-generated method stub
            return position;
        }

        public long getItemId(int position) {
            // TODO Auto-generated method stub
            return position;
        }

        public View getView(final int position, View convertView,
                ViewGroup parent) {
            // Avoid unneccessary calls to findViewById() on each row, which is
            // expensive!

            holder = null;

            if (convertView == null) {
                convertView = getLayoutInflater().inflate(
                        R.layout.adapter_main, null);
                holder = new ViewHolder(convertView);

                // Create a ViewHolder and store references to the children
                // views
                holder.textName = (TextView) convertView
                        .findViewById(R.id.textName);
                holder.thumbnail = (ImageView) convertView
                        .findViewById(R.id.thumbnail);
                holder.btnUpload = (Button) convertView
                        .findViewById(R.id.btnUpload);
                holder.textStatus = (TextView) convertView
                        .findViewById(R.id.textStatus);

                // The tag can be any Object, this just happens to be the
                // ViewHolder
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
            holder.btnUpload.setEnabled(ImageList.get(position)
                    .isStatusEnable());
            holder.textStatus.setText(ImageList.get(position).getMessage());
            strPath = ImageList.get(position).getImages().toString();

            // Get File Name
            fileName = strPath.substring(strPath.lastIndexOf('/') + 1,
                    strPath.length());
            File file = new File(strPath);
            @SuppressWarnings("unused")
            long length = file.length();
            holder.textName.setText(fileName);

            final BitmapFactory.Options options = new BitmapFactory.Options();

            Bitmap bm = BitmapFactory.decodeFile(strPath, options);
            holder.thumbnail.setImageBitmap(bm);

            // btnUpload
            holder.btnUpload.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    // Upload
                    startUpload(position);
                }
            });

            return convertView;

        }
    }

    // Upload

    public void startUpload(final int position) {

        Runnable runnable = new Runnable() {

            public void run() {

                handler.post(new Runnable() {

                    public void run() {
                        v = lstView.getChildAt(position
                                - lstView.getFirstVisiblePosition());
                        holder = (ViewHolder) v.getTag();
                        synchronized (this) {
                            ImageList.get(position).setStatusEnable(false);
                            mAdapter.notifyDataSetChanged();
                        }

                        new UploadFileAsync().execute(String.valueOf(position));
                    }
                });
            }
        };
        new Thread(runnable).start();
    }

    // Async Upload
    public class UploadFileAsync extends AsyncTask<String, Void, Void> {

        String resServer;

        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected Void doInBackground(String... params) {
            position = Integer.parseInt(params[0]);
            int bytesRead, bytesAvailable, bufferSize;
            byte[] buffer;
            int maxBufferSize = 1 * 1024 * 1024;
            int resCode = 0;
            String resMessage = "";

            String lineEnd = "\r\n";
            String twoHyphens = "--";
            String boundary = "*****";

            // File Path
            String strSDPath = ImageList.get(position).getImages().toString();

            // Upload to PHP Script
            String strUrlServer = "http://mymasterpeice.comxa.com/uploadFile.php";

            try {
                /** Check file on SD Card ***/
                File file = new File(strSDPath);
                if (!file.exists()) {
                    resServer = "{\"StatusID\":\"0\",\"Message\":\"Please check path on SD Card\"}";
                    return null;
                }

                FileInputStream fileInputStream = new FileInputStream(new File(
                        strSDPath));

                URL url = new URL(strUrlServer);
                HttpURLConnection conn = (HttpURLConnection) url
                        .openConnection();
                conn.setDoInput(true);
                conn.setDoOutput(true);
                conn.setUseCaches(false);
                conn.setRequestMethod("POST");

                conn.setRequestProperty("Connection", "Keep-Alive");
                conn.setRequestProperty("Content-Type",
                        "multipart/form-data;boundary=" + boundary);

                DataOutputStream outputStream = new DataOutputStream(
                        conn.getOutputStream());
                outputStream.writeBytes(twoHyphens + boundary + lineEnd);
                outputStream
                        .writeBytes("Content-Disposition: form-data; name=\"filUpload\";filename=\""
                                + strSDPath + "\"" + lineEnd);
                outputStream.writeBytes(lineEnd);

                bytesAvailable = fileInputStream.available();
                bufferSize = Math.min(bytesAvailable, maxBufferSize);
                buffer = new byte[bufferSize];

                // Read file
                bytesRead = fileInputStream.read(buffer, 0, bufferSize);

                while (bytesRead > 0) {
                    outputStream.write(buffer, 0, bufferSize);
                    bytesAvailable = fileInputStream.available();
                    bufferSize = Math.min(bytesAvailable, maxBufferSize);
                    bytesRead = fileInputStream.read(buffer, 0, bufferSize);
                }

                outputStream.writeBytes(lineEnd);
                outputStream.writeBytes(twoHyphens + boundary + twoHyphens
                        + lineEnd);

                // Response Code and Message
                resCode = conn.getResponseCode();
                if (resCode == HttpURLConnection.HTTP_OK) {
                    InputStream is = conn.getInputStream();
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();

                    int read = 0;
                    while ((read = is.read()) != -1) {
                        bos.write(read);
                    }

                    byte[] result = bos.toByteArray();
                    bos.close();

                    resMessage = new String(result);

                }

                Log.d("resCode=", Integer.toString(resCode));
                Log.d("resMessage=", resMessage.toString());

                fileInputStream.close();
                outputStream.flush();
                outputStream.close();

                resServer = resMessage.toString();

            } catch (Exception ex) {
                ex.printStackTrace();
            }

            return null;
        }

        protected void onPostExecute(Void unused) {
            statusWhenFinish(position, resServer);
        }

    }

    // When Upload Finish
    @SuppressWarnings("unused")
    protected void statusWhenFinish(int position, String resServer) {

        /*** Default Value ***/
        String strStatusID = "0";
        String strError = "";

        try {

            JSONObject c = new JSONObject(resServer);
            strStatusID = c.getString("StatusID");
            strError = c.getString("Message");
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // // prepare Status
        if (strStatusID.equals("0")) {
            // When update Failed
            ImageList.get(position).setMessage("Failed");
            ImageList.get(position).setStatusEnable(true);
            mAdapter.notifyDataSetChanged();
        } else {
            ImageList.get(position).setMessage("Uploded");
            ImageList.get(position).setStatusEnable(false);
            mAdapter.notifyDataSetChanged();
        }

    }

    /**
     * Introduce a class with below attributes to hold a state of each row in
     * single element
     * 
     */
    public class MyData {
        /* Image url or path of image in single row */
        private String images;

        /* anme of image in single row */
        private String name;

        /* status ID of image in single row */
        private String statusID;

        /* message of image in single row */
        private String message;

        private boolean statusEnable;

        public boolean isStatusEnable() {
            return statusEnable;
        }

        public void setStatusEnable(boolean statusEnable) {
            this.statusEnable = statusEnable;
        }

        // Generate getters and setter
        public String getImages() {
            return images;
        }

        public void setImages(String images) {
            this.images = images;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getStatusID() {
            return statusID;
        }

        public void setStatusID(String statusID) {
            this.statusID = statusID;
        }

        public String getMessage() {
            return message;
        }

        public void setMessage(String message) {
            this.message = message;
        }

    }

}

答案 1 :(得分:1)

创建要使用的数据类型列表。例如。

class YourDataType{
    String name, status;
    Bitmap image;
}

然后使用列表来保存列表中的所有对象。

List<YourDataType> listOfObjects;

然后使用类似参数创建适配器,并将对象列表传递给适配器的构造函数。

class ImagesAdapter extends BaseAdapter{
    public ImagesAdapter(Context c, List<YourDataType> listOfObjects){
        this.listOfObjects = listOfObjects;
    }

    public View getView(params, position){
        YourDataType data = listOfObjects.get(position);
        //Here you can use data to access specific object and upload the specific image and then mark this object's status to marked, then you can change the status of any listview item relevant to the object.
        if(data.status == uploaded)
             viewHolder.textStatus.setText("Uploaded");
    }
}

最佳做法是分离适配器 希望能帮助到你。如果您有任何进一步的问题,请在下面发表评论。

答案 2 :(得分:0)

你应该有一个Upload Status数组,它将被传递给适配器,默认值为false,每次你在服务器上成功上传文件,都会将状态更改为与listitem相对应的数组。

例如

默认数组(假设列表大小为7)

{"false","false""false""false""false""false""false"}  

每次成功上传文件时,请将Array的状态更改为

{"false","true""false""false""false""false""true"}

现在您只需要更新此数组中的值,并且必须调用

youradapter.notifydatasetchanged();