当我尝试从 ListView 中向下拖动一行时出现“IndexOutOfBoundsException”(使用 DragSortListView)

Posted

技术标签:

【中文标题】当我尝试从 ListView 中向下拖动一行时出现“IndexOutOfBoundsException”(使用 DragSortListView)【英文标题】:I got "IndexOutOfBoundsException" when I try to drag down a row from my ListView (using DragSortListView) 【发布时间】:2017-08-12 21:01:07 【问题描述】:

我在 youtube 上看到了一个教程,展示了如何将数据添加到 sqlLite db,然后将这些数据显示到 ListView Video。

这样做之后...我将 DragSortListView 应用到我的列表视图...但每次我拖动一行。这个错误不断出现,我无法解决它:

FATAL EXCEPTION: main
Process: com.example.justi.ricksonbar, PID: 29157
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
  at java.util.ArrayList.get(ArrayList.java:411)
  at com.example.justi.ricksonbar.ProductAdapter.getItem(ProductAdapter.java:49)
  at com.example.justi.ricksonbar.BackgroundTask$1.drop(BackgroundTask.java:91)
  at com.mobeta.android.dslv.DragSortListView.dropFloatView(DragSortListView.java:1501)
  at com.mobeta.android.dslv.DragSortListView.access$1200(DragSortListView.java:59)
  at com.mobeta.android.dslv.DragSortListView$DropAnimator.onStop(DragSortListView.java:1293)
  at com.mobeta.android.dslv.DragSortListView$SmoothAnimator.run(DragSortListView.java:1192)
  at android.os.Handler.handleCallback(Handler.java:751)
  at android.os.Handler.dispatchMessage(Handler.java:95)
  at android.os.Looper.loop(Looper.java:154)
  at android.app.ActivityThread.main(ActivityThread.java:6119)
  at java.lang.reflect.Method.invoke(Native Method)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

这是我的 ProductAdapter.java¨

import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.TextView;

import com.mobeta.android.dslv.DragSortController;
import com.mobeta.android.dslv.DragSortListView;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class ProductAdapter extends ArrayAdapter
    List list = new ArrayList();


    public ProductAdapter(Context context,int resource) 
        super(context, resource);
    

    public void add(Product object) 
        list.add(object);
        super.add(object);
    


    @Override
    public int getCount() 
        return list.size();
    

    @Override
    public Object getItem(int position) 
        return list.get(position);
    

    @Override
    public View getView(int position, final View convertView, ViewGroup parent) 
        View row = convertView;
        final ProductHolder productHolder;
        if(row == null)
            LayoutInflater layoutInflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = layoutInflater.inflate(R.layout.product_list, parent, false);
            productHolder = new ProductHolder();
            productHolder.tx_name = (TextView)row.findViewById(R.id.tvProd_name);
            productHolder.tx_price = (TextView)row.findViewById(R.id.tvProd_price);
            productHolder.tx_type = (TextView)row.findViewById(R.id.tvProd_type);
            row.setTag(productHolder);
        else
            productHolder = (ProductHolder) row.getTag();
        
        Product product = (Product) getItem(position);
        productHolder.tx_name.setText(product.getName().toString());
        productHolder.tx_price.setText(Double.toString(product.getPrice()));
        productHolder.tx_type.setText(product.getType().toString());

        return row;
    

    static class ProductHolder
        TextView tx_name, tx_price, tx_type;
    


和我的 BackgroundTask.java(我放 DragSortListView 方法的地方)

import android.app.Activity;
import android.app.VoiceInteractor;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.mobeta.android.dslv.DragSortController;
import com.mobeta.android.dslv.DragSortListView;

public class BackgroundTask extends AsyncTask<String, Product, String>  
    Context ctx;
    ProductAdapter productAdapter;
    Activity activity;
    DragSortListView listView;

    BackgroundTask(Context ctx)
        this.ctx = ctx;
        activity = (Activity)ctx;
    

    @Override
    protected void onPreExecute() 
        super.onPreExecute();

    

    @Override
    protected String doInBackground(String... params) 

        String method = params[0];
        DatabaseHelper dHelper = new DatabaseHelper(ctx);

        if (method.equals("add_info"))
            String name = params[1];
            double price = Double.parseDouble(params[2]);
            String type = params[3];
            SQLiteDatabase db = dHelper.getWritableDatabase();
            //Call method of insertion
            dHelper.addInformations(db, name, price, type);
            return "One row is inserted....";

        else if (method.equals("get_info"))
            listView = (DragSortListView)activity.findViewById(R.id.display_listview);
            SQLiteDatabase db = dHelper.getReadableDatabase();
            Cursor cursor = dHelper.getInformations(db);
            productAdapter = new ProductAdapter(ctx,R.layout.product_list);
            String name, type;
            double price;
            while (cursor.moveToNext())
                name = cursor.getString(cursor.getColumnIndex(ProductContract.ProductEntry.NAME));
                price = cursor.getDouble(cursor.getColumnIndex(ProductContract.ProductEntry.PRICE));
                type = cursor.getString(cursor.getColumnIndex(ProductContract.ProductEntry.TYPE));
                Product product = new Product(name, price, type);
                publishProgress(product);
            

            return "get_info";
        
        return null;
    

    @Override
    protected void onProgressUpdate(Product... values) 
        productAdapter.add(values[0]);

    

    private DragSortListView.DropListener onDrop = new DragSortListView.DropListener()
    
        @Override
        public void drop(int from, int to)
        
            productAdapter = new ProductAdapter(ctx,R.layout.product_list);
            if (from != to)
            
                Object item = productAdapter.getItem(from);
                productAdapter.remove(item);
                productAdapter.insert(item, to);
            
        
    ;

    private DragSortListView.RemoveListener onRemove = new DragSortListView.RemoveListener()
    
        @Override
        public void remove(int which)
        
            productAdapter = new ProductAdapter(ctx,R.layout.product_list);
            productAdapter.remove(productAdapter.getItem(which));
        
    ;

    @Override
    protected void onPostExecute(String result) 

        if (result.equals("get_info"))
            listView.setAdapter(productAdapter);
            listView.setDropListener(onDrop);
            listView.setRemoveListener(onRemove);

            DragSortController controller = new DragSortController(listView);
            controller.setRemoveEnabled(false);
            controller.setSortEnabled(true);
            controller.setDragInitMode(1);

            listView.setFloatViewManager(controller);
            listView.setOnTouchListener(controller);
            listView.setDragEnabled(true);
        else
            Toast.makeText(ctx, result, Toast.LENGTH_LONG).show();
        
    

请帮助我。非常感谢

【问题讨论】:

【参考方案1】:

您正在尝试在适配器中添加任何元素之前获取项目。

@Override
    public void drop(int from, int to)
       // Adapter is Created here
        productAdapter = new ProductAdapter(ctx,R.layout.product_list);
        if (from != to)
        
            // here you are trying to get item which must throw indexoutofbounds 
            // because you didn't added anything yet
            Object item = productAdapter.getItem(from);
            productAdapter.remove(item);
            productAdapter.insert(item, to);
        
    

根据你的adapter的add方法会在Adapter中添加元素。

public void add(Product object) 
    list.add(object);
    super.add(object);

【讨论】:

哦,好的。这就说得通了。现在我在想我可以把那个“drop”方法放在哪里。必须在数据添加之后 像这样从 Adapter 中获取 Items 确实不是一个好主意,而是通过 Adapter 您可以传递您的 Items 的引用。 真的吗?我不知道,正如您显然可以看到的,我是 Android 的初学者。我只是看到了这个教程,并从头开始遵循它。 是的,阅读更多关于 AsyncTasks 的内容,您就会知道在异步任务中使用视图/适配器是多么危险。【参考方案2】:

使用Cursor Adapter,效率更高:

https://guides.codepath.com/android/Populating-a-ListView-with-a-CursorAdapter

【讨论】:

可以作为评论添加。

以上是关于当我尝试从 ListView 中向下拖动一行时出现“IndexOutOfBoundsException”(使用 DragSortListView)的主要内容,如果未能解决你的问题,请参考以下文章

Swift NSTableview 拖动选择多行而不是拖出表格

将 swift storyboard 上的所有控件从屏幕顶部向下拖动,但运行时它们又回到屏幕顶部

listview向下滑动过程中背景色变成黑色和一些奇怪问题

从ArrayAdapter每毫秒更新Android ListView中的一行

从工作表 1 引用工作表 2 中的单元格,但在工作表 1 中每次向下拖动时索引该行

尝试将数据从Intent迁移到ListView,但出现了一些错误