2014-04-18 78 views
2

Im使用cwac-endlessEndlessAdapter與自定義ListViewAdapter。通過一個AsyncTask,我可以分兩個階段獲取webserver的數據表單。 1)我得到使用,我想加載EndlessAdapter元素 2)的所有ID說,在同一時間(我從服務器獲取4件4個元素通過其ID)EndlessAdapter無法正確添加項目到自定義ListView

的問題,即時通訊面臨的是,當我創建我的custom ListViewAdapter時,我調用MyEndlessAdapter的構造函數創建項目的第一個項目的列表。當我加載下一批元素我的自定義ListViewAdapter它從服務器獲取正確的項目,但我回收getView(圖形/視覺的東西)。我究竟做錯了什麼!

我認爲可能的解決方案是使用的add方法,但我不知道如何從CompraFragment類中調用它。

我該如何解決這個問題? 由於

ListViewAdapter代碼:

public class ListViewAdapter extends ArrayAdapter<Item> { 

    private LayoutInflater inflater = null; 
    private final String TAG = "ListViewAdapter"; 
    public Context context; 
    public int layoutResourceId; 
    public ArrayList<Item> items; 


    public ListViewAdapter(Context context, int listviewItemRow, ArrayList<Item> items) { 
     // TODO Auto-generated constructor stub 
     super(context, listviewItemRow); 
     this.context = context; 
     this.items = items; 

    } 

    public ListViewAdapter(Context context, int listviewItemRow) { 
     super(context, listviewItemRow); 
     this.context = context; 
    } 


    @Override 
    public void add(Item object) { 
     Log.i(TAG, "---ADD---"); 
     items.add(object); 
     //super.add(object); 
    } 

    @Override 
    public void clear() { 
     super.clear(); 
    } 

    @Override 
    public void notifyDataSetChanged() { 
     super.notifyDataSetChanged(); 
    } 

    @Override 
    public void remove(Item object) { 
     super.remove(object); 
    } 

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

    public Item getItem(Item position) { 
     return position; 
    } 

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

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

     Item item = items.get(position); 
     Log.w(TAG, "view of Item " + item.getId() + " at position " + position); 

     ItemView view; 
     if (convertView == null) { 
      inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      view = (ItemView) inflater.inflate(R.layout.listview_item_row, null); 
      view.checkFollowing(item, this, 3); 
      view.setTag(Long.toString(item.getId()));  
      Log.e(TAG, "CREATED ITEM " + item.getId() + " at position " + position); 
     } else { 
      view = (ItemView) convertView; 
      Log.i(TAG, "RECYCLED ITEM " + item.getId() + " at position " + position); 
     } 

     view.setOnClickListener(new OnItemClickListener(position)); 



     view.showItems(item); 
     return view; 
    } 


    private class OnItemClickListener implements OnClickListener { 

     private int mPosition; 

     private OnItemClickListener(int position){ 
      mPosition = position; 
     } 

     @Override 
     public void onClick(View v) { 
      Toast.makeText(context, "Message " + Integer.toString(mPosition), Toast.LENGTH_SHORT).show(); 

      Intent intent = new Intent(context, DettagliActivity.class); 
      Bundle bundle = new Bundle(); 
      bundle.putInt("id", mPosition); 
      intent.putExtras(bundle); 
      context.startActivity(intent); 
     } 
    } 

} 

CompraFragment代碼:

public class CompraFragment extends ListFragment { 

    private static final String TAG = "CompraFragment"; 
    public ListView listView; 
    public MyEndlessAdapter adapter = null; 
    public ListViewAdapter mListViewAdapter; 

    private DownloadTask mDownloadTask = null; 

    public ArrayList<Item> items; 
    public ArrayList<Long> ids; 
    public Bitmap icon; 
    public int currentItemId = 0; 

    public String category = ""; 
    public String latitude = ""; 
    public String longitude = ""; 
    public String radius = ""; 
    public String keywords = ""; 
    public String order = ""; 
    public String state = "2"; 

    //numero di elementi caricabili sulla wall all volta 
    public final int BATCH_SIZE = 4;  

    public ProgressDialog progressDialog; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setHasOptionsMenu(true); 
     progressDialog = new ProgressDialog(this.getActivity()); 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     // Handle action bar actions click 
     switch (item.getItemId()) { 
     case R.id.action_aggiorna: 

      items = new ArrayList<Item>(); 
      ids = new ArrayList<Long>(); 

      mDownloadTask = new DownloadTask(); 
      mDownloadTask.execute(); 
      return true; 
     default: 
      return super.onOptionsItemSelected(item); 
     } 
    } 


    @Override 
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 
     // TODO Auto-generated method stub 
     inflater.inflate(R.menu.compra, menu); 
     super.onCreateOptionsMenu(menu, inflater); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     Log.i(TAG, "onCreateView"); 
     Bundle extras = getActivity().getIntent().getExtras(); 

     if (extras != null){ 
      category = (String) extras.get("category"); 
      latitude = (String) extras.get("latitude"); 
      longitude = (String) extras.get("radius"); 
      radius = (String) extras.get("radius"); 
      keywords = (String) extras.get("keywords"); 
      order = (String) extras.get("order"); 
      state = (String) extras.get("state"); 
     } 

     View rootView = inflater.inflate(R.layout.fragment_compra, container, false); 

     // now you must initialize your list view 
     listView = (ListView) rootView.findViewById(android.R.id.list); 

     mDownloadTask = new DownloadTask(); 
     mDownloadTask.execute(); 

     return rootView; 
    } 



    /** 
    * Represents an asynchronous task used to download 
    * information from the webserver and display the results 
    */ 
    public class DownloadTask extends AsyncTask<Integer, Void, Boolean> { 

     @Override 
     protected Boolean doInBackground(Integer... params) {   
      ids = new ArrayList<Long>();  

      ids = MVPFunctions.getInstance().search(category, latitude, longitude, radius, keywords, order, state); 

      if (ids.isEmpty()){ 
       return false; 
      } else { 
       Log.i(TAG, "ids size = " + ids.size()); 
      } 
      return true; 
     } 

     @Override 
     protected void onPreExecute(){ 
      /* 
      * This is executed on UI thread before doInBackground(). It is 
      * the perfect place to show the progress dialog. 
      */ 
      //progressDialog = ProgressDialog.show(getActivity(), "", "Downloading Content..."); 
      progressDialog.setMessage("Downloading Content..."); 
      progressDialog.show(); 
     } 

     @Override 
     protected void onPostExecute(final Boolean success) { 
      mDownloadTask = null; 

      if (!success){ 
       Log.i("onPostExecute", "items null"); 
       Toast.makeText(getActivity(), "Non ci sono elementi da caricare", Toast.LENGTH_LONG).show(); 
      } else { 
       items = new ArrayList<Item>(); 
       adapter = new MyEndlessAdapter(items); 
       adapter.setRunInBackground(false); 
       listView.setAdapter(adapter); 
      } 
     } 

     @Override 
     protected void onCancelled() { 
      mDownloadTask = null; 
     }  
    } 


    class MyEndlessAdapter extends EndlessAdapter implements IItemsReadyListener { 
     private RotateAnimation rotate = null; 

     MyEndlessAdapter(ArrayList<Item> list) { 
      super(new ListViewAdapter(getActivity(),R.layout.listview_item_row, list)); 
      rotate = new RotateAnimation(0f, 360f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); 
      rotate.setDuration(600); 
      rotate.setRepeatMode(Animation.RESTART); 
      rotate.setRepeatCount(Animation.INFINITE); 

      Log.i(TAG, "CONSTRUCTER CALLED"); 
     } 


     @Override 
     protected View getPendingView(ViewGroup parent) { 
      View row = getActivity().getLayoutInflater().inflate(R.layout.listview_item_row, null); 
      View child; 

      child = row.findViewById(R.id.relativeLayout); 
      child.setVisibility(View.GONE); 

      child = row.findViewById(R.id.throbber); 
      child.setVisibility(View.VISIBLE); 
      child.startAnimation(rotate); 

      return (row); 
     } 

     @Override 
     protected boolean cacheInBackground() throws Exception {    
      //Log.i(TAG, "cacheInBackground - items.size(): " + items.size()); 

      new FetchDataTask(this, items.size()).execute(); 

      if (items.size() < ids.size()){ 
       return true; 
      } else { 
       return false; 
      } 
     } 

     @Override 
     public void onItemsReady(ArrayList<Item> data) { 
      Log.e(TAG, "onItemsReady"); 
      items.addAll(data); 

      // Tell the EndlessAdapter to remove it's pending view and call notifyDataSetChanged() 
      adapter.onDataReady(); 
      progressDialog.dismiss(); 
     } 

     @Override 
     protected void appendCachedData() { 
      // TODO Auto-generated method stub 
     } 
    } 

    interface IItemsReadyListener { 
     public void onItemsReady(ArrayList<Item> data); 
    } 

    class FetchDataTask extends AsyncTask<Void, Void, ArrayList<Item>> { 
     private static final String TAG = "FetchDataTask"; 

     IItemsReadyListener listener; 

     //The point from where to start counting. 
     int startPoint; 


     protected FetchDataTask(IItemsReadyListener listener, int startPoint) { 
      this.listener = listener; 
      this.startPoint = startPoint; 
     } 

     @Override 
     protected ArrayList<Item> doInBackground(Void... params) { 
      ArrayList<Item> result = new ArrayList<Item>(); 

      Item item; 
      for (int i = startPoint; ((i < ids.size()) && (i < startPoint + BATCH_SIZE)); i++) { 
       Log.i(TAG, "i = " + i); 
       item = MVPFunctions.getInstance().getItem(ids.get(i)); 
       result.add(item); 
      } 
      return (result); 
     } 

     @Override 
     protected void onPostExecute(ArrayList<Item> result) { 
      listener.onItemsReady(result); 

     } 
    } 
} 

ItemView控件代碼:

public class ItemView extends LinearLayout { 

    public TextView prezzo; 
    public TextView scadenza; 
    public TextView followers; 
    public ImageView ic_thumbnail; 
    public ProgressBar hProgressBar; 
    public ToggleButton followButton; 
    public String nextFollowAction = ""; 
    public ListViewAdapter lva; 

    public String mLogin; 
    public String mPassword; 

    public int statusCode; 
    public Item item; 


    public BackgroundTask mBackgroundTask = null; 


    public ItemView(Context context, AttributeSet attrs) { 
     super(context, attrs);  

    } 



    @Override 
    protected void onFinishInflate() { 
     super.onFinishInflate(); 
     prezzo = (TextView)findViewById(R.id.tvPrezzo); 
     scadenza = (TextView)findViewById(R.id.tvScadenza); 
     followers = (TextView)findViewById(R.id.tvFollowers); 
     ic_thumbnail = (ImageView)findViewById(R.id.ic_thumbnail); 
     hProgressBar = (ProgressBar)findViewById(R.id.hProgressBar); 
     followButton = (ToggleButton)findViewById(R.id.btnFollow); 
    } 

    public void showItems(final Item item) { 
     prezzo.setText(item.getPrezzo()); 
     ic_thumbnail.setImageBitmap(item.getIcon()); 
     scadenza.setText(item.getScadenza()); 
     followers.setText("Followers: " + item.getFollowers()); 
     hProgressBar.setProgress(item.getCoefficient()); 
     followButton.setTag(item.getId()); 
    } 


    public void askForFollowing(String nextFollowAction, final Item item, final int statusCode){ 

     //Log.e("status code fo item is", Integer.toString(statusCode) + " " + item.getId()); 
     //Status code: 0 --> OK  
     if(statusCode == 0) { 
      //Log.i("statusCode == 0", "richiesta evasa correttamente"); 
      changeFollowStatus(nextFollowAction, item); 
     } 

     // Status code 108 --> Oggetto già seguito 
     else if ((statusCode == 108) && (nextFollowAction.contains("kCheckFollowAction"))) { 
      //Log.i("statusCode == 108", "gray"); 
      nextFollowAction = "kUnfollowAction"; 
      followButton.setEnabled(true); 
      followButton.setBackgroundResource(R.drawable.action_object_button_gray); 
      followButton.setText("seguito"); 
      lva.notifyDataSetChanged(); 

      followButton.setOnClickListener(new View.OnClickListener() { 
       @Override 
       public void onClick(View view) { 
        view.setEnabled(false); 
        setFollowing("kUnfollowAction", item, (long) 2); 
       } 
      }); 
     } 

     // Status code 122 --> Oggetto non ancora seguito 
     else if ((statusCode == 122) && (nextFollowAction.contains("kCheckFollowAction"))) { 
      //Log.i("statusCode == 122", "green"); 
      nextFollowAction = "kFollowAction"; 
      followButton.setEnabled(true); 
      followButton.setBackgroundResource(R.drawable.action_object_button_green); 
      followButton.setText("segui"); 
      lva.notifyDataSetChanged(); 

      followButton.setOnClickListener(new View.OnClickListener() { 
       @Override 
       public void onClick(View view) {     
        view.setEnabled(false); 
        setFollowing("kFollowAction", item, (long) 1); 
       } 
      }); 

     } else { 
      Log.e("error", "error non e ne 0 ne 108 ne 122"); 
      Log.e("error", nextFollowAction); 
      Log.e("error", Long.toString(item.getId())); 
      Log.e("error", Integer.toString(statusCode)); 
     } 

    } 

    public void changeFollowStatus(String nextFollowAction, Item item){ 
     //Log.i("changeFollowStatus action", nextFollowAction); 

     if(nextFollowAction.contains("kFollowAction")) { 
      //Log.w("changeFollowStatus increase", "+1"); 
      nextFollowAction = "kUnfollowAction"; 
      followButton.setBackgroundResource(R.drawable.action_object_button_gray); 
      followButton.setText("seguito"); 
      followButton.getTextOn(); 
      increaseFollowers(item);   
     } 
     else if(nextFollowAction.contains("kUnfollowAction")){ 
      //Log.w("changeFollowStatus decrease", "-1"); 
      nextFollowAction = "kFollowAction"; 
      followButton.setBackgroundResource(R.drawable.action_object_button_green); 
      followButton.setText("segui"); 
      followButton.getTextOff(); 
      decreaseFollowers(item); 
     } 
    } 

    public void increaseFollowers(Item item){ 
     int updatedFollowers = Integer.parseInt(item.getFollowers()) + 1; 
     item.setFollowers(Integer.toString(updatedFollowers)); 
     followers.setText("Followers: " + item.getFollowers()); 
    } 

    public void decreaseFollowers(Item item){ 
     int updatedFollowers = Integer.parseInt(item.getFollowers()) - 1; 
     item.setFollowers(Integer.toString(updatedFollowers)); 
     followers.setText("Followers: " + item.getFollowers()); 
    } 

    public void checkFollowing(Item item, ListViewAdapter listViewAdapter, long follow) { 

     this.lva = listViewAdapter; 

     mBackgroundTask = new BackgroundTask(); 
     try { 
      int statusCode = mBackgroundTask.execute(item.getId(), follow).get(); 
      askForFollowing("kCheckFollowAction", item, statusCode); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } catch (ExecutionException e) { 
      e.printStackTrace(); 
     } 

    } 

    public void setFollowing(String nextFollowAction, Item item, Long follow){ 

     mBackgroundTask = new BackgroundTask(); 

     try { 
      int statusCode = mBackgroundTask.execute(item.getId(), follow).get(); 

      /* 
      Log.i("setFollowing p1", Long.toString(follow)); 
      Log.i("setFollowing p1", nextFollowAction); 
      Log.i("setFollowing p2", Long.toString(item.getId())); 
      Log.i("setFollowing p3", Integer.toString(statusCode)); 
      */ 
      askForFollowing(nextFollowAction, item, statusCode); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (ExecutionException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 



    /** 
    * Represents an asynchronous task used to download 
    * information from the webserver and display the results 
    */ 
    public class BackgroundTask extends AsyncTask<Long, Void, Integer> { 

     private int statusCode; 

     @Override 
     protected Integer doInBackground(Long... params) { 
      // TODO: attempt authentication against a network service. 



      statusCode = MVPFunctions.getInstance().followItem(mLogin, mPassword, params[0], params[1].intValue()); 

      return statusCode; 
     } 

     @Override 
     protected void onPreExecute(){ 
      /* 
      * This is executed on UI thread before doInBackground(). It is 
      * the perfect place to show the progress dialog. 
      */ 
     } 

     @Override 
     protected void onPostExecute(Integer result) { 
      mBackgroundTask = null; 

      //askForFollowing("kCheckFollowAction", item, statusCode); 

      //listViewAdapter.notifyDataSetChanged(); 

      //result1 = listener.processFinish(result); 

      //setStatusCode(result); 

      //delegate.processFinish(result); 
      //ItemView 
      //Log.i("onPostExecute statusCode", Integer.toString(success) + " = " + Integer.toString(statusCode)); 
     } 

     @Override 
     protected void onCancelled() { 
      mBackgroundTask = null; 
     } 
    } 
} 

回答

1

當視圖再循環[即,傳遞給getView()作爲非-null convertView],你需要更新它以反映當前的狀態item。因此,需要在if/then塊之後移動下面所示的2行。

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

    Item item = items.get(position); 
    Log.w(TAG, "view of Item " + item.getId() + " at position " + position); 

    ItemView view; 
    if (convertView == null) { 
     inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     view = (ItemView) inflater.inflate(R.layout.listview_item_row, null); 
     Log.e(TAG, "CREATED ITEM " + item.getId() + " at position " + position); 
    } else { 
     view = (ItemView) convertView; 
     Log.i(TAG, "RECYCLED ITEM " + item.getId() + " at position " + position); 
    } 

    // ===> These 2 lines always need to be executed. <=== 
    view.checkFollowing(item, this, 3); 
    view.setTag(Long.toString(item.getId()));  

    view.setOnClickListener(new OnItemClickListener(position)); 

    view.showItems(item); 
    return view; 
} 
+0

問題是checkFollowing(params)方法會對服務器進行調用,因此是時間成本高昂的方法。如果我把它放在if(然後在回收對象中),那麼每當我向下移動listView時它就會被調用,這使得它真的很慢。 – Pheonix7

+0

但是當視圖被回收時,它仍然會有它原來的狀態,這可能是你最初的問題。也許你可以將你已經計算好的狀態緩存在單獨的內存集合中,這樣你最多隻需要計算一次項目的狀態。 – cybersam

+0

不,你只需要一個狀態對象的集合(因爲它看起來像你的每個項目都有多個狀態屬性)。說一個HashMap ,其中Integer是該項目的位置,ItemState封裝了該項目在該位置的狀態。儘管如此,請注意ItemState - 您不希望它引用任何視圖,因爲這會導致內存泄漏,並使其更有可能會耗盡內存。 – cybersam

相關問題