首页 > 解决方案 > 调用 setAdapter(cursorAdapter) 方法时应用程序崩溃

问题描述

我正在尝试创建一个应用程序,它可以使用片段根据指定的搜索字符串显示联系人列表。但该应用程序似乎在布局绘制期间崩溃,没有做任何事情或显示任何内容。

ContactsFragment.java 的代码:

package com.example.contacts;
import ...

public class ContactsFragment extends Fragment implements
        LoaderManager.LoaderCallbacks<Cursor>,
        AdapterView.OnItemClickListener {
    @SuppressLint("InlinedApi")
    private final static String[] FROM_COLUMNS = {
            ContactsContract.Contacts.DISPLAY_NAME_PRIMARY
    };
    private final static int[] TO_IDS = {
            android.R.id.text1
    };
    ListView contactsList;
    long contactID;
    String contactKey;
    Uri contactURI;

    public ContactsFragment(){}

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.contact_list, container, false);
    }
    SimpleCursorAdapter cursorAdapter;

    @SuppressLint("ResourceType")
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        contactsList = Objects.requireNonNull(getActivity()).findViewById(R.id.contact_list);
        cursorAdapter = new SimpleCursorAdapter(getActivity(),
                                                R.layout.contact_list_item,
                                                null,
                                                FROM_COLUMNS,
                                                TO_IDS,
                                                0);
        contactsList.setAdapter(cursorAdapter);       //THROWS NULL POINTER EXCEPTION
        contactsList.setOnItemClickListener(this);
    }

    @SuppressLint("InlinedApi")
    private static final String[] PROJECTION =
            {
                    ContactsContract.Contacts._ID,
                    ContactsContract.Contacts.LOOKUP_KEY,
                    ContactsContract.Contacts.DISPLAY_NAME_PRIMARY
            };
    private static final int CONTACT_ID_INDEX = 0;
    private static final int CONTACT_KEY_INDEX = 1;

    @SuppressLint("InlinedApi")
    private static final String SELECTION = ContactsContract.Contacts.DISPLAY_NAME_PRIMARY + " LIKE ?";
    private String searchString="";
    private String[] selectionArgs = { searchString };

    @Override
    public void onItemClick(AdapterView<?> parent, View item, int position, long rowID) {
        Cursor cursor = ((CursorAdapter)(parent.getAdapter())).getCursor();
        cursor.moveToPosition(position);
        contactID = cursor.getLong(CONTACT_ID_INDEX);
        contactKey = cursor.getString(CONTACT_KEY_INDEX);
        contactURI = ContactsContract.Contacts.getLookupUri(contactID, contactKey);
        /*
         * You can use contactUri as the content URI for retrieving
         * the details for a contact.
         */
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LoaderManager.getInstance(this).initLoader(0, null, this);
    }

    @NonNull
    @Override
    public Loader<Cursor> onCreateLoader(int id, @Nullable Bundle args) {
        /*
         * Makes search string into pattern and
         * stores it in the selection array
         */
        selectionArgs[0] = "%" + searchString + "%";
        // Starts the query
        return new CursorLoader(
                Objects.requireNonNull(getActivity()),
                ContactsContract.Contacts.CONTENT_URI,
                PROJECTION,
                SELECTION,
                selectionArgs,
                null
        );
    }

    @Override
    public void onLoadFinished(@NonNull Loader<Cursor> loader, Cursor cursor) {
        cursorAdapter.swapCursor(cursor);
    }

    @Override
    public void onLoaderReset(@NonNull Loader<Cursor> loader) {
        cursorAdapter.swapCursor(null);
    }
}

错误出现在引发. 我还没有创建搜索小部件,因为我无法正确解析布局和链接。contactsList.setAdapter(cursorAdapter);NullPointerException

还有MainActivity.java文件:

package com.example.contacts;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

我附上activity_main.xml供参考:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">
    <fragment
        android:id="@+id/contact_view"
        android:name="com.example.contacts.ContactsFragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

我为片段布局使用了两个文件——contact_list.xml它们contact_list_item.xml分别是:

<?xml version="1.0" encoding="utf-8"?>

<ListView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/contact_list_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

</ListView>
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/text1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:clickable="true"
    android:focusable="true" />

这个想法是片段将有一个ListView包含单个项目的TextView.

我已经提到该应用程序在应用程序的清单文件中使用联系人权限。

以下是崩溃日志:

   --------- beginning of crash
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.contacts, PID: 25682
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.contacts/com.example.contacts.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a null object reference
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2724)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2789)
        at android.app.ActivityThread.-wrap12(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1527)
        at android.os.Handler.dispatchMessage(Handler.java:110)
        at android.os.Looper.loop(Looper.java:203)
        at android.app.ActivityThread.main(ActivityThread.java:6251)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a null object reference
        at com.example.contacts.ContactsFragment.onActivityCreated(ContactsFragment.java:56)
        at androidx.fragment.app.Fragment.performActivityCreated(Fragment.java:2619)
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:904)
        at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1238)
        at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1303)
        at androidx.fragment.app.FragmentManagerImpl.dispatchStateChange(FragmentManagerImpl.java:2659)
        at androidx.fragment.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManagerImpl.java:2613)
        at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:246)
        at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:542)
        at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:201)
        at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1248)
        at android.app.Activity.performStart(Activity.java:6683)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2687)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2789) 
        at android.app.ActivityThread.-wrap12(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1527) 
        at android.os.Handler.dispatchMessage(Handler.java:110) 
        at android.os.Looper.loop(Looper.java:203) 
        at android.app.ActivityThread.main(ActivityThread.java:6251) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924) 
I/art: Enter while loop.

如果有人可以帮助我,我将不胜感激,因为我对 Android 编程很陌生。

标签: javaandroidxmlandroid-fragments

解决方案


该错误NullPointerException是由于代码试图访问(或绑定)到尚未使用的 id 的事实。

其中给出的idfindViewById应该R.id.contact_list_view R.id.contact_list


推荐阅读