尝试在空对象引用上调用虚拟方法 - 抽屉布局

Attempt to invoke virtual method on a null object reference - drawer layout

我正在创建一个扩展 ActionBarActivity 的父级 activity,我的所有活动都将扩展它(因此我只需设置一次抽屉)。

我一直在抽屉列表的 setAdapter 方法上收到空指针异常,但无法弄清楚原因。

这是父级 activity: (崩溃日志显示这是 activity 的原因,我在该行的末尾添加了注释)

import android.app.Activity;
import android.content.res.Configuration;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.makeramen.RoundedImageView;
import com.makeramen.RoundedTransformationBuilder;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.Transformation;


public class MainActivity extends ActionBarActivity implements AdapterView.OnItemClickListener {

    // Action bar
    private ActionBar actionBar;
    private Toolbar toolbar;

    // Navigation Drawer
    private ActionBarDrawerToggle drawerToggle;
    private DrawerLayout drawerLayout;
    private ListView drawerList;
    private RelativeLayout drawerHeader;
    private ImageView drawerHeaderBG;
    private RoundedImageView userImage;
    private TextView userName;

    public void setupActivity() {
        setMyActionBar();
        createDrawer();
    }

    public void setMyActionBar() {
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        toolbar.setTitleTextColor(Color.WHITE);

        setSupportActionBar(toolbar);
        actionBar = getSupportActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);
        actionBar.setHomeButtonEnabled(true);
        actionBar.setTitle(getString(R.string.app_name));
        actionBar.setDisplayShowTitleEnabled(true);
        actionBar.setDisplayHomeAsUpEnabled(getSupportFragmentManager().getBackStackEntryCount() > 0);
    }

    public void createDrawer() {
        drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawerLayout.post(new Runnable() {
            @Override
            public void run() {
                drawerList = (ListView) drawerLayout.findViewById(R.id.left_drawer);
                drawerList.setMinimumWidth(((View) findViewById(R.id.baseLayoutRootParent)).getWidth() - actionBar.getHeight());

                if (drawerList.getHeaderViewsCount() == 0)
                    drawerList.addHeaderView(drawerHeader);

                drawerList.setAdapter(new DrawerAdapter(MainActivity.this)); // crash happens here

                drawerList.setOnItemClickListener(MainActivity.this);

                drawerToggle = new ActionBarDrawerToggle(
                        MainActivity.this,                  /* host Activity */
                        drawerLayout,         /* DrawerLayout object */
                        R.drawable.ic_action_navigation_menu,  /* nav drawer icon to replace 'Up' caret */
                        R.string.open_drawer,  /* "open drawer" description */
                        R.string.close_drawer  /* "close drawer" description */
                ) {

                    /**
                     * Called when a drawer has settled in a completely closed state.
                     */
                    public void onDrawerClosed(View view) {
                        actionBar.setTitle(getString(R.string.app_name));
                    }

                    /**
                     * Called when a drawer has settled in a completely open state.
                     */
                    public void onDrawerOpened(View drawerView) {
                        actionBar.setTitle(getString(R.string.app_name));
                    }
                };

                // Set the drawer toggle as the DrawerListener
                drawerLayout.setDrawerListener(drawerToggle);
                drawerToggle.syncState();
            }
        });

    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        // drawer list item click events
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        drawerToggle.onConfigurationChanged(newConfig);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.

        if (drawerToggle.onOptionsItemSelected(item)) {
            return true;
        }

        switch (item.getItemId()) {
            case R.id.action_settings:
                return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

这是扩展前一个的 activity:

public class HomeActivity extends MainActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_layout);
        setupActivity();

        getSupportFragmentManager().beginTransaction().replace(R.id.mainContainer, MainFragment.newInstance()).commit();

    }
}

这是抽屉列表的适配器:

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class DrawerAdapter extends BaseAdapter {

    private Context context;
    private String[] items;

    public DrawerAdapter(Context context) {
        this.context = context;
        items = context.getResources().getStringArray(R.array.drawer_array);
    }

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

    @Override
    public String getItem(int position) {
        return items[position];
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            holder = new ViewHolder();
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.drawer_list_item, parent, false);

            holder.image = (ImageView) convertView.findViewById(R.id.drawerItemImage);
            holder.text = (TextView) convertView.findViewById(R.id.drawerItemText);

            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.image.setImageResource(getIcon(position));
        holder.text.setText(getItem(position));

        return convertView;
    }

    private int getIcon(int position) {
        switch (position) {
            case 0:
                return R.drawable.ic_action_home_blue;
            case 1:
                return R.drawable.ic_action_heart_blue;
            case 2:
                return R.drawable.ic_action_search_blue;
            case 3:
                return R.drawable.ic_action_map_blue;
            case 4:
                return R.drawable.ic_action_wheel_blue;
            case 5:
                return R.drawable.ic_action_calendar_blue;
            case 6:
                return R.drawable.ic_action_parameters_blue;
        }

        return 0;
    }

    class ViewHolder {
        private ImageView image;
        private TextView text;
    }
}

为了以防万一,这里是布局文件:

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="?attr/color">
    <!-- The main content view -->

    <LinearLayout
        android:id="@+id/baseLayoutRootParent"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <android.support.v7.widget.Toolbar xmlns:bar="http://schemas.android.com/apk/res-auto"
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:gravity="end|center_vertical"
            android:paddingEnd="@dimen/activity_horizontal_margin"
            android:paddingLeft="@dimen/activity_horizontal_margin"
            android:paddingRight="@dimen/activity_horizontal_margin"
            android:paddingStart="@dimen/activity_horizontal_margin"
            bar:theme="@style/ThemeOverlay.AppCompat.ActionBar" />

        <FrameLayout
            android:id="@+id/mainContainer"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>
    <!-- The drawer content view -->

    <ListView
        android:id="@+id/left_drawer"
        android:layout_width="250dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="?attr/background"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp" />
</android.support.v4.widget.DrawerLayout>

最后,这是错误日志:

02-27 13:05:55.205  11723-11723/com.example.myApp.app E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.example.myApp.app, PID: 11723
    java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.ViewGroup$LayoutParams android.view.View.getLayoutParams()' on a null object reference
            at android.widget.ListView.clearRecycledState(ListView.java:539)
            at android.widget.ListView.resetList(ListView.java:525)
            at android.widget.ListView.setAdapter(ListView.java:469)
            at com.example.myApp.app.MainActivity.run(MainActivity.java:92)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:155)
            at android.app.ActivityThread.main(ActivityThread.java:5696)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1028)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)

提前致谢!

编辑

我试过从 onCreate、onPostCreate 和 onResume 调用 setupActivity() 并在所有 3 个中都得到相同的错误

所以,我也遇到了这个奇怪的错误,但我的错误日志没有指向我的应用程序中的任何代码行,所以这是一个关于问题出在哪里的猜谜游戏。 它是:

listView.scrollToPosition(0);
Cursor results = performQuery();
if(results != null){
    adapter.changeCursor(results);
}

我的崩溃是在没有结果的情况下发生的,所以我最终决定使用空视图。

Cursor results = performQuery();
if(results != null && results.getCount() > 0){
    listView.setVisibility(View.VISIBLE);
    emptyView.setVisibility(View.GONE);
    adapter.changeCursor(results);
    listView.scrollToPosition(0);
}
else{
    emptyView.setVisibility(View.VISIBLE);
    listView.setVisibility(View.GONE);
}

这解决了我的崩溃问题。请注意,我使用的是新的 RecyclerView.