我需要动态控制研究与的AsyncTask自定义的ListView的按钮的行为(I need to d

2019-10-19 05:47发布

林做一个电子商务应用程序,并在我的墙上我有很多产品(我称之为项目)。 因此,所有这些项目都是通过定制看到ListView称为ListViewAdapter 。 所述customListView的每行具有不同的View相似的元件TextViewButtonImage等。 Button ,我已是一个后续按钮(也就是说,如果用户正在以下某一个项目这个按钮应该被看作灰色说法随后,如果用户没有遵循它,然后它应该是绿色的说法如下)。

所以,当我加载数据的ListView的第一次,我需要做此项检查,看看是否一个项目是beeing跟随或没有(这个功能是通过在做后台服务器调用来完成,并根据我知道,如果响应其beeing其次与否)。 另外,我需要实现的功能,当我在它在后台服务器调用(得到一个结果为0,如果操作succeded)某一个项目的后续按钮点击,改变颜色和文字。

我做了管理的ItemView控件类View项目的s和我的问题在这里棱:

  1. 如何管理的事实,我需要动态地管理跟踪Button (很显然,我需要使用的AsyncTask),但我在哪里可以管理它? 在ItemView控件类或ListViewAdapter的每一行?

  2. 我需要管理这3个服务器调用一起:让所有的物品,看看哪一个之后还是不行,如果我选择一个项目遵循它。

我读了很多,我应该使用adapter.notifyDataSetChanged()但在何处以及如何?

我敢肯定,我不是第一人问这样的问题。 我想,大多数电子商务应用程序具有相同的行为。 能否请你告诉我这是如何高效地完成。 谢谢!

这里是我的代码:

ListViewAdapter类

public class ListViewAdapter extends ArrayAdapter<String> {

    private LayoutInflater inflater = null;

    public Context context; 
    public int layoutResourceId;
    public ArrayList<Item> items;
    public Bitmap icon;

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

    @Override
    public void remove(String object) {
        // TODO Auto-generated method stub
        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) {

        ItemView view;
        if (convertView == null) {
            inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = (ItemView) inflater.inflate(R.layout.listview_item_row, null);
        } else {
            view = (ItemView) convertView;
        }

        Item item = items.get(position);
        view.showItems(item);
        view.setOnClickListener(new OnItemClickListener(position));

        return view;
    }

    private class OnItemClickListener implements OnClickListener {

        private int mPosition;

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

        @Override
        public void onClick(View v) {

            Log.i("onListItemClickList", "Item clicked: " + mPosition);
            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);
        }   
    }

ItemView控件类

public class ItemView extends LinearLayout implements AsyncResponse{

    public TextView prezzo;
    public TextView scadenza;
    public TextView followers;
    public ImageView ic_thumbnail;
    public ProgressBar hProgressBar;
    public ToggleButton followButton;
    public String nextFollowAction = "";
    public Integer result1 = 77;
    public int statusCode;
    public Item item;

    public BackgroundTask mBackgroundTask = null;

    public ItemView(Context context, AttributeSet attrs) {
        super(context, attrs);
        //mBackgroundTask.delegate = this;
        // TODO Auto-generated constructor stub
    }

    @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());


        askForFollowing("kCheckFollowAction", item, 3);


        mBackgroundTask = new BackgroundTask(this);
    mBackgroundTask.execute(item.getId(), (long)3);

    followButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    // The toggle is enabled
                    Log.i("followButton", "toggle enabled");
                    followButton.getTextOn();
                    mBackgroundTask = new BackgroundTask(ItemView.this);
                    mBackgroundTask.execute(item.getId(), (long)1);
                    //askForFollowing(result1, nextFollowAction, item);
                    //askForFollowing(statusCode, nextFollowAction, item);
                    increaseFollowers(item);
                    followButton.setBackgroundResource(R.drawable.action_object_button_gray);
                } else {
                    // The toggle is disabled
                    Log.i("followButton", "toggle disabled");
                    mBackgroundTask = new BackgroundTask(ItemView.this);
                    mBackgroundTask.execute(item.getId(), (long)2);
                    //askForFollowing(result1, nextFollowAction, item);
                    followButton.getTextOff();
                    followButton.setBackgroundResource(R.drawable.action_object_button_green);
                    decreaseFollowers(item);
                }
            }
        });
    }

    public void setStatusCode(int statusCode){
        this.statusCode = statusCode;
    }


    public int getStatusCode(Item item, int follow){
        //add thread that waits untill you have the statusCode
        mBackgroundTask = new BackgroundTask(ItemView.this);
        mBackgroundTask.execute(item.getId(), (long) follow);

        return statusCode;
    }

    public void askForFollowing(String nextFollowAction, Item item, int follow){
         Log.i("The statusCode is", Integer.toString(statusCode));
         Log.i("The nextFollowAction is", nextFollowAction);

         int statusCode = getStatusCode(item, follow);

         //Status code: 0 --> OK
         if(statusCode == 0) {
            Log.i("changeFollowStatus(nextFollowAction);", "changeFollowStatus(nextFollowAction);");
            nextFollowAction = "kCheckFollowAction";
            changeFollowStatus(nextFollowAction, item);
         }

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

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

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

        if(action.contains("kFollowAction")) {
            Log.i("changeFollowStatus", "1");
            nextFollowAction = "kUnfollowAction";
            followButton.setBackgroundResource(R.drawable.action_object_button_gray);
            followButton.setText("seguito");
            followButton.getTextOn();
            increaseFollowers(item);        
        }
        else if(action.contains("kUnfollowAction")){
            Log.i("changeFollowStatus", "2");
            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());
    }

    @Override
    public Integer processFinish(Integer result) {
        return result;
    }

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

        //public AsyncResponse delegate;
        private AsyncResponse listener;

        public BackgroundTask(AsyncResponse listener){
            this.listener = listener;
        }

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

            int i = MVPFunctions.getInstance().followItem(SessionManager.getUserDetails().get("login"), SessionManager.getUserDetails().get("password"), params[0], params[1].intValue());
            return i;
        }

        @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;
            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;
            //showProgress(false);
        }
    }
}

CompraFragment类

public class CompraFragment extends ListFragment {

    public ListView listView;
    public ListViewAdapter adapter;
    public boolean loading = false;
    public boolean get_all_items = false;
    //public PullToRefreshScrollView mPullRefreshScrollView;

    /**
     * Keep track of the login task to ensure we can cancel it if requested.
     */
    private DownloadTask mDownloadTask = null;
    private Boolean firstTime = true;

    //public ArrayList<HashMap<String, Object>> items = new ArrayList<HashMap<String, Object>>();
    public ArrayList<Item> items = new ArrayList<Item>();
    public static ArrayList<Long> ids = new ArrayList<Long>();
    public Bitmap icon;
    public int currentItemId = 0;
    public Boolean noItems = false;

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

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        //View rootView = inflater.inflate(R.layout.fragment_compra, false); 
        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.execute((Void) null);   
        mDownloadTask = new DownloadTask();
        mDownloadTask.execute(currentItemId);

        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> {

        private ProgressDialog progressDialog;

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

            if (firstTime){
                ids = MVPFunctions.getInstance().search();
                firstTime = false;
            }

            if (ids.isEmpty()){
                noItems = true;
                return false;
            }

            int current_id = params[0];


            // 5 elements at a time
            int counter = 0;
            int size = ids.size();  

            while (counter <= 5 && (current_id < size)) {
                items.add(MVPFunctions.getInstance().getItem(ids.get(current_id)));
                current_id++;
                counter++;
                currentItemId = current_id;
            }

            if(current_id == size){
                get_all_items = true;
            }

            Log.i("current_id    2", Integer.toString(current_id));
            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...");
        }

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

            // dismiss the dialog after getting all products
            progressDialog.dismiss();
            loading = false;
            //showProgress(false);

            Log.i("onPostExecute", "onPostExecute");

            if (noItems){
                Log.i("doInBackground2", "items null");
                Toast.makeText(getActivity(), "Non ci sono elementi da caricare", Toast.LENGTH_LONG).show();
            } else {
                        // updating UI from Background Thread
                ListViewAdapter adapter = new ListViewAdapter(getActivity(),R.layout.listview_item_row, items, icon);
                        // updating listview
                    listView.setAdapter(adapter);

                    listView.setOnScrollListener(new EndlessScrollListener());                          
            }

        }

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

    }

    public class EndlessScrollListener implements OnScrollListener {

        private int visibleThreshold = 6;
        private int previousTotal = 0;


        public EndlessScrollListener() {
        }
        public EndlessScrollListener(int visibleThreshold) {
            this.visibleThreshold = visibleThreshold;
        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            if (loading) {
                if (totalItemCount > previousTotal) {
                    loading = false;
                    previousTotal = totalItemCount;
                }
            }

            if (!loading && visibleItemCount != 0 && ((firstVisibleItem + visibleItemCount) >= (totalItemCount))) {
                if ((currentItemId <= ids.size()) && !get_all_items){               
                    loading = true;
                    mDownloadTask = new DownloadTask();
                    mDownloadTask.execute(currentItemId);
                }
            }
            /*
            if (visibleItemCount != 0 && ((firstVisibleItem + visibleItemCount) >= (totalItemCount))) {
                if (currentItemId <= ids.size()){
                    Log.i("3333 if", "3333 if");
                    mDownloadTask = new DownloadTask();
                    mDownloadTask.execute(currentItemId);
                }
            }
            */
        }

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
        }
    }
}

Answer 1:

我做了类似的东西! 我改变了我的适配器类动态地添加的ToggleButtons

看看这个链接,例如:

检查切换按钮动态地



Answer 2:

其作为基础,甚至比显示您的更新跟踪/跟随状态更重要的Button是你的应用程序的响应能力 ,我会做到以下几点:

  • 你不应该拖延地的加载ListView只是为了更新后的数据加载它。 在这里,反应是网络速度(甚至是网络的可否订购)的90%的责任 - 我会加载所有的项目没有更新的状态(比如,显示了“关注”按钮)。

  • 你知道你需要更新你的按钮的状态。 初始化适配器后,立即,我开始放送您AsyncTask

  • 作为“通信法”,我建议本地广播 。 原因很简单:你的内处理您的信息AsyncTask ,你需要通过你的适配器来进行分配。 他们使用的引用之间的通信不是一件简单的事情。 另外,你需要尽可能多的速度成为可能。 另外,你会送(假设你需要行ID或标签,和一个布尔标记该行是否必须显示后续或随后状态)的数据序列化,这使得它非常适合这种情况。

因此,在实际的一面,这就是我想要做的:

在你的阵列适配器,具体在getView()方法,当你吹你行,标志着具有唯一标识符(比如,项目名称)该行的每个按钮。 您可以通过这样做setTag("itemname")View的对象(第二个参数)。

仍然在你的阵列适配器扩展,定义了一个本地广播接收机是这样的:

class MyItemBroadcast extends BroadcastReceiver {
  @Override
  public void onReceive(final Context context, final Intent intent) {
    if (intent.getAction().equals("ItemUpdate")) {
      final String itemname = intent.getStringExtra("itemname");
      final Boolean follow = intent.getBooleanExtra("is_following");
      if (itemname != null) {
        final ListView myListView = (ListView) findViewById(R.id.your_listview_id);
        final Button = (Button) myListView.findViewWithTag(itemname);

        if (follow) {
          // Here you would assign one of the layouts (follow or already followed)
          ...
        }
        else {
          // The other one
          ...
        }

        // You have to call this to make the observers update the ListView layout.
        // One of them is your activity/fragment itself, who has the instance of your
        // adapter, so you're telling it to update the layout with this change
        notifyDataSetChanged();
      }
    }
  }
}

// Now you need to declare the receiver and register it
final MyItemBroadcast bc_receive = new MyItemBroadcast();
LocalBroadcastManager.getActivity().registerReceiver(bc_receive, new IntentFilter("ItemUpdate"));

做完这一点,那么你只需要处理您的事件AsyncTask和你内发出“信号”声明了接收器,这样AsyncTask ,每当你需要更新项目,就发出这样的事情:

final Intent intentResult = new Intent("ItemUpdate");
intentResult.putExtra("itemname", "my_item_to_update");
intentResult.putExtra("is_following", true);
LocalBroadcastManager.getInstance(this).sendBroadcast(intentResult);          

就这样,你的扩展ArrayListAdapter应该被处理的新事件时更新。 我还没有尝试过这样的事,你可能会发现拼写错误或小错误,而我更accostumed比与片段活动的工作,也许你就必须找到一些类比(您在StackOverflow的将是肯定的),但这是想法和它的作品。 不要忘了unregisterReceiver()一旦你不需要它了!



Answer 3:

  • 分派事件到ViewGroup中的儿童,使用onInterceptTouchEvent : 链接

  • 要管理的“关注”按钮刷新:

    1. getView你的方法ListViewAdapter ,检查当前项目之后,改变按钮的背景。 设置标签,就可以buttonView这可能是在ArrayList中的项目(在buttonView使用setTag)项的指标并设置onClickListener(在视图上的标签可以让你任何类型的数据附加到一个视图)。

    2. 在你onClickListener ,通过调用获得该项目的索引view.getTag()并获取相应的项目。 然后才能运行与项目ID您的HTTP请求执行的AsyncTask。 我想这对你的网络服务器这一要求店,这个项目之后。

    3. 在适配器中定义为随后与位置参数来设置项目的方法: void setIsFollowed(int position) 。 在onPostExecute您的AsyncTask的,运行的方法setIsFollowed(position) ,以更改适配器源。 然后,强制的ListView通过调用与修改后的阵列来更新它listView.notifyDataSetChanged

我希望这是明确的...

编辑:

public void setIsFollowed(int position, boolean isfollowed) {  
 Item myItem = Items.get(position);   

 if (myItem != null)   
    //don't forget to add "boolean isFollowed" in the Item class   
    myItem.isFollowed = isfollowed;
 }


Answer 4:

尽量让所有的“下面的数据:”你填充ListView之前。

如果您可以修改服务器端,写一个方法为它获得更多信息“跟随”这些ID的状态。 那么你的适配器getView方法可以检查布尔(类似:isFollowing())数据,并根据它改变按钮。 通过这种方式,所有你需要做的就是改变数据集和之后通知适配器。

它是确定改变单一的数据在列表视图的AsyncTask。

编辑:

如果是这样,你打电话给你的AsyncTask在你的适配器getView()方法

getView(){
    //convertView ect. blah. do the same stuff to populate your list
    new CheckfollowTask(btnFollow, items.get(position)).execute();


}

//Type parameters can change in your need this is just an example, a pseudo.
class CheckfollowTask extends AsyncTask<Void,Void,Void>{

Button btnFollow;
Item item;
       CheckfollowTask(Button btnFollow,Item item){
       this.btnFollow=btnFollow;
       this.item=item;
       }
      donInBackGround(){
      //get data from server
      }
      onPostExecute(){
      //set btnFollow's background to something due to your response from server.
      //don't forget to set your list items followin status.
      item.setFollow(response);
      }

}


文章来源: I need to dynamically controll the behaviour of a button of a custom listView with AsyncTask