快速滚动时的NullPointerException [英] NullPointerException when scrolling fast

查看:185
本文介绍了快速滚动时的NullPointerException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想包括分类字段到我coustom的ListView。直到我开始滚动快,它工作正常。当滚动很慢,不会发生此​​错误。这真是困惑我。谁能请帮助?
我的code:

I'm trying to include category fields into my coustom ListView. It works fine until I start scrolling fast. When scrolling very slow this error doesn't occur. It's really confusing me. Could anyone please help? My Code:

package com.mamlambo.tutorial.tutlist;

import java.util.ArrayList;
import java.util.TreeSet;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.ImageView;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

public class TutListActivity extends Activity {

private DatabaseManager mHelper;
private SQLiteDatabase mDatenbank;
private ArrayList<String> devicesList;
private TreeSet<Object> mSeparatorsSet;
ListView listView;
EfficientAdapter objectAdapter;

private class EfficientAdapter extends BaseAdapter {
    private LayoutInflater mInflater;
    private Bitmap mIcon1;
    private Bitmap mIcon2;

    private static final int TYPE_ITEM = 0;
    private static final int TYPE_SEPARATOR = 1;
    private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;

    public EfficientAdapter(Context context) {
        // Cache the LayoutInflate to avoid asking for a new one each time.
        mInflater = LayoutInflater.from(context);

        // Icons bound to the rows.
        mIcon1 = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon);
        mIcon2 = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon);
    }

    /**
     * The number of items in the list is determined by the number of speeches
     * in our array.
     *
     * @see android.widget.ListAdapter#getCount()
     */
    public int getCount() {
        return devicesList.size();
    }

    public void addItem(final String item) {
        devicesList.add(item);
        notifyDataSetChanged();
    }

    /**
     * Since the data comes from an array, just returning the index is
     * sufficent to get at the data. If we were using a more complex data
     * structure, we would return whatever object represents one row in the
     * list.
     *
     * @see android.widget.ListAdapter#getItem(int)
     */
    public Object getItem(int position) {
        return position;
    }
    /**
     * Use the array index as a unique id.
     *
     * @see android.widget.ListAdapter#getItemId(int)
     */
    public long getItemId(int position) {
        return position;
    }

    @Override
    public void notifyDataSetChanged() // Create this function in your adapter class
    {
        super.notifyDataSetChanged();
    }

    public void addSeparatorItem(final String item) {
        devicesList.add(item);
        // save separator position
        mSeparatorsSet.add(devicesList.size() - 1);
        notifyDataSetChanged();
    }

    @Override
    public int getItemViewType(int position) {
        return mSeparatorsSet.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        // A ViewHolder keeps references to children views to avoid unneccessary calls
        // to findViewById() on each row.
        ViewHolder holder;
        // When convertView is not null, we can reuse it directly, there is no need
        // to reinflate it. We only inflate a new View when the convertView supplied
        // by ListView is null.
        int type = getItemViewType(position);

        if (convertView == null) {

            holder = new ViewHolder();

            switch (type) {
                case TYPE_ITEM:

                    convertView = mInflater.inflate(R.layout.list_item, null);

                    holder.text = (TextView) convertView.findViewById(R.id.Title_List_Item);
                    holder.icon = (ImageView) convertView.findViewById(R.id.Delete_List_Item);

                    convertView.findViewById(R.id.Title_List_Item).setTag(devicesList.get(position));
                    convertView.findViewById(R.id.Delete_List_Item).setTag(devicesList.get(position));

                    holder.text.setText(devicesList.get(position));
                    holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);

                    holder.text.setOnClickListener(mOnTitleClickListener);
                    holder.icon.setOnClickListener(mOnIconClickListener);

                    break;

                case TYPE_SEPARATOR:

                    convertView = mInflater.inflate(R.layout.seperator_item, null);

                    holder.text = (TextView)convertView.findViewById(R.id.Text_Seperator_Item);

                    holder.text.setText(devicesList.get(position));

                    break;
            }

            convertView.setTag(holder);

        } else {
            // Get the ViewHolder back to get fast access to the TextView
            // and the ImageView.
            holder = (ViewHolder) convertView.getTag();
        }
        return convertView;
    }


    private OnClickListener mOnTitleClickListener = new OnClickListener() {
        public void onClick(View v) {
                if(v.getTag().toString() == "ADD DEVICE"){
                    Intent addDevice = new Intent(getApplicationContext(), addDevice.class);
                    startActivity(addDevice);
                }else{
                    Intent showRemote = new Intent(TutListActivity.this, Remote.class);
                    showRemote.putExtra("selectedDevice", v.getTag().toString());
                    startActivity(showRemote);
                }
        }
    };

    private OnClickListener mOnIconClickListener = new OnClickListener() {
        public void onClick(View v) {
            String NameOfDevice[] = new String[2];
            NameOfDevice = v.getTag().toString().split(",");
            mDatenbank.execSQL("DELETE FROM addedDevices WHERE name = '"+NameOfDevice[0]+"'");

            ladeDevices();
            objectAdapter.notifyDataSetChanged();
        }
    };

    class ViewHolder {
        TextView text;
        ImageView icon;
    }
}


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

    setContentView(R.layout.mainlayout);

    mHelper = new DatabaseManager(this);
    mDatenbank = mHelper.getReadableDatabase();

    listView = (ListView) findViewById(R.id.list);
    objectAdapter = new EfficientAdapter(this);

    ladeDevices();
}

/*

@Override
protected void onPause() {
    super.onPause();
    mDatenbank.close();
    dataloaded = false;
}

@Override
protected void onResume() {
    super.onResume();
    mDatenbank = mHelper.getReadableDatabase();
    ladeDevices();
}

*/

private void ladeDevices() {
        devicesList = new ArrayList<String>();
        mSeparatorsSet = new TreeSet<Object>();

        Cursor devicesCursor = mDatenbank.query("addedDevices", new String[] {"name", "hersteller"}, null, null, null, null, null);
        startManagingCursor(devicesCursor);
        devicesCursor.moveToFirst();

        for (int i=0;i<devicesCursor.getCount();i++){ 
            String addingElement = new String(devicesCursor.getString(0)+", "+devicesCursor.getString(1));
            objectAdapter.addItem(addingElement);
            devicesCursor.moveToNext();
            if (i % 4 == 0) {
                objectAdapter.addSeparatorItem("separator " + i);
            }
        } 
        objectAdapter.addItem("ADD DEVICE");
        listView.setAdapter(objectAdapter);
    }

}

谢谢!

编辑:
LogCat中输出:

LogCat Output:

11-19 15:01:44.898: E/AndroidRuntime(957): FATAL EXCEPTION: main
11-19 15:01:44.898: E/AndroidRuntime(957): java.lang.NullPointerException
11-19 15:01:44.898: E/AndroidRuntime(957):  at com.mamlambo.tutorial.tutlist.TutListActivity$EfficientAdapter.getView(TutListActivity.java:150)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.widget.AbsListView.obtainView(AbsListView.java:2012)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.widget.ListView.makeAndAddView(ListView.java:1772)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.widget.ListView.fillUp(ListView.java:705)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.widget.ListView.correctTooHigh(ListView.java:1395)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.widget.ListView.fillGap(ListView.java:637)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.widget.AbsListView.trackMotionScroll(AbsListView.java:4546)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.widget.AbsListView.scrollIfNeeded(AbsListView.java:2852)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.widget.AbsListView.onTouchEvent(AbsListView.java:3106)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.view.View.dispatchTouchEvent(View.java:5486)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1953)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1714)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1959)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1728)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1959)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1728)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1959)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1728)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1959)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1728)
11-19 15:01:44.898: E/AndroidRuntime(957):  at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1892)
11-19 15:01:44.898: E/AndroidRuntime(957):  at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1371)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.app.Activity.dispatchTouchEvent(Activity.java:2364)
11-19 15:01:44.898: E/AndroidRuntime(957):  at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1840)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.view.View.dispatchPointerEvent(View.java:5662)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:2863)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2442)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.os.Handler.dispatchMessage(Handler.java:99)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.os.Looper.loop(Looper.java:137)
11-19 15:01:44.898: E/AndroidRuntime(957):  at android.app.ActivityThread.main(ActivityThread.java:4340)
11-19 15:01:44.898: E/AndroidRuntime(957):  at java.lang.reflect.Method.invokeNative(Native Method)
11-19 15:01:44.898: E/AndroidRuntime(957):  at java.lang.reflect.Method.invoke(Method.java:511)
11-19 15:01:44.898: E/AndroidRuntime(957):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
11-19 15:01:44.898: E/AndroidRuntime(957):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
11-19 15:01:44.898: E/AndroidRuntime(957):  at dalvik.system.NativeStart.main(Native Method)

编辑:
我添加了一个新的版本。我把listView.setAdapter(objectAdapter);从数据库加载列表中的条目,并将它们在ArrayList中的方法内。这样,将适配器设置新的每次改变的东西(项beeing删除)。这样做可以让我把setTag()和onClickListener()调用到,如果(convertView == NULL){...}让那些只当事情的变化,而不是每次getView()被调用调用。我相信,这一定是重大失误,虽然我不知道如果我的解决方案是一个非常不错的。

edit: I added a new Version. I put the listView.setAdapter(objectAdapter); inside the method that loads the list entries from the Database and puts them in the ArrayList. That way the Adapter is set new every time something changes (entries are beeing deleted). Doing this allows me to put the setTag() and onClickListener() calls into the if (convertView == null) {...} so that those are only called when something changes and not everytime getView() is called. I believe that this must have been the major mistake, although I'm not sure if my solution is a very good one.

推荐答案

声明

View view = null;

在适配器类实例变量
您else部分应该是这样的。

as instance variable in adapter class Your else part should look like this

else {
        view = convertView;
}
holder = (ViewHolder) convertView.getTag();

这篇关于快速滚动时的NullPointerException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆