片段崩溃与 setOnClickListener

Posted

技术标签:

【中文标题】片段崩溃与 setOnClickListener【英文标题】:Fragment crash with setOnClickListener 【发布时间】:2016-03-14 09:24:53 【问题描述】:

我有不同的活动来扩展 BaseActivity。当我点击按钮时:

public class Item1Activity extends BaseActivity 
Button button1;
@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    button1 = (Button) findViewById(R.id.button1);

    /**
     *  We will not use setContentView in this activity 
     *  Rather than we will use layout inflater to add view in FrameLayout of our base activity layout*/

    /**
     * Adding our layout to parent class frame layout.
     */
    getLayoutInflater().inflate(R.layout.activity_main, frameLayout);
    button1.setOnClickListener(new View.OnClickListener() 
        public void onClick(View view) 
            Intent intent = new Intent(
                    android.content.Intent.ACTION_VIEW,
                    Uri.parse("http://maps.google.com/maps?daddr=46.0796808,13.2393894,17z"));
            startActivity(intent);
        
    );

当我启动应用程序时,它会因 NullPointerException 而崩溃。 这是日志:

12-09 08:30:44.305: E/AndroidRuntime(740): Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
12-09 08:30:44.305: E/AndroidRuntime(740):  at com.navigation.drawer.activity.Item1Activity.onCreate(Item1Activity.java:30)

我的基本活动是:

public class BaseActivity extends Activity 

/**
 *  Frame layout: Which is going to be used as parent layout for child activity layout.
 *  This layout is protected so that child activity can access this  
 *  */
protected FrameLayout frameLayout;

/**
 * ListView to add navigation drawer item in it.
 * We have made it protected to access it in child class. We will just use it in child class to make item selected according to activity opened.  
 */

protected ListView mDrawerList;

/**
 * List item array for navigation drawer items. 
 * */
protected String[] listArray =  "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" ;

/**
 * Static variable for selected item position. Which can be used in child activity to know which item is selected from the list.  
 * */
protected static int position;

/**
 *  This flag is used just to check that launcher activity is called first time 
 *  so that we can open appropriate Activity on launch and make list item position selected accordingly.    
 * */
private static boolean isLaunch = true;

/**
 *  Base layout node of this Activity.    
 * */
private DrawerLayout mDrawerLayout;

/**
 * Drawer listner class for drawer open, close etc.
 */
private ActionBarDrawerToggle actionBarDrawerToggle;


@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.navigation_drawer_base_layout);

    frameLayout = (FrameLayout)findViewById(R.id.content_frame);
    mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    mDrawerList = (ListView) findViewById(R.id.left_drawer);


    mDrawerList.setAdapter(new ArrayAdapter<String>(this,      R.layout.drawer_list_item, listArray));
         mDrawerList.setOnItemClickListener(new OnItemClickListener() 

        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) 

            openActivity(position);
        
    );

    // enable ActionBar app icon to behave as action to toggle nav drawer
    getActionBar().setDisplayHomeAsUpEnabled(true);
    getActionBar().setHomeButtonEnabled(true);

    // ActionBarDrawerToggle ties together the the proper interactions between the sliding drawer and the action bar app icon
    actionBarDrawerToggle = new ActionBarDrawerToggle(
            this,                       /* host Activity */
            mDrawerLayout,              /* DrawerLayout object */
            R.drawable.ic_launcher,     /* nav drawer image to replace 'Up' caret */
            R.string.open_drawer,       /* "open drawer" description for accessibility */
            R.string.close_drawer)      /* "close drawer" description for accessibility */ 
     
        @Override
        public void onDrawerClosed(View drawerView) 
            getActionBar().setTitle(listArray[position]);
            invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
            super.onDrawerClosed(drawerView);
        

        @Override
        public void onDrawerOpened(View drawerView) 
            getActionBar().setTitle(getString(R.string.app_name));
            invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
            super.onDrawerOpened(drawerView);
        

        @Override
        public void onDrawerSlide(View drawerView, float slideOffset) 
            super.onDrawerSlide(drawerView, slideOffset);
        

        @Override
        public void onDrawerStateChanged(int newState) 
            super.onDrawerStateChanged(newState);
        
    ;
    mDrawerLayout.setDrawerListener(actionBarDrawerToggle);


    /**
     * As we are calling BaseActivity from manifest file and this base activity is intended just to add navigation drawer in our app.
     * We have to open some activity with layout on launch. So we are checking if this BaseActivity is called first time then we are opening our first activity.
     * */
    if(isLaunch)
         /**
          *Setting this flag false so that next time it will not open our first activity.
          *We have to use this flag because we are using this BaseActivity as parent activity to our other activity. 
          *In this case this base activity will always be call when any child activity will launch.
          */
        isLaunch = false;
        openActivity(0);
    


/**
 * @param position
 * 
 * Launching activity when any list item is clicked. 
 */
protected void openActivity(int position) 

    /**
     * We can set title & itemChecked here but as this BaseActivity is parent for other activity, 
     * So whenever any activity is going to launch this BaseActivity is also going to be called and 
     * it will reset this value because of initialization in onCreate method.
     * So that we are setting this in child activity.    
     */
    mDrawerList.setItemChecked(position, true);
    setTitle(listArray[position]);
    mDrawerLayout.closeDrawer(mDrawerList);
    BaseActivity.position = position;

    switch (position) 
    case 0:
        startActivity(new Intent(this, Item1Activity.class));
        break;
    case 1:
        startActivity(new Intent(this, Item2Activity.class));
        break;
    case 2:
        startActivity(new Intent(this, Item3Activity.class));
        break;
    case 3:
        startActivity(new Intent(this, Item4Activity.class));
        break;
    case 4:
        startActivity(new Intent(this, Item5Activity.class));
        break;

    default:
        break;
    

    Toast.makeText(this, "Selected Item Position::"+position, Toast.LENGTH_LONG).show();


@Override
public boolean onCreateOptionsMenu(Menu menu) 

    getMenuInflater().inflate(R.menu.main, menu);
    return super.onCreateOptionsMenu(menu);


@Override
public boolean onOptionsItemSelected(MenuItem item) 

    // The action bar home/up action should open or close the drawer. 
    // ActionBarDrawerToggle will take care of this.
    if (actionBarDrawerToggle.onOptionsItemSelected(item)) 
        return true;
    

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

    default:
        return super.onOptionsItemSelected(item);
    


/* Called whenever we call invalidateOptionsMenu() */
@Override
public boolean onPrepareOptionsMenu(Menu menu) 
    // If the nav drawer is open, hide action items related to the content view
    boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
    menu.findItem(R.id.action_settings).setVisible(!drawerOpen);
    return super.onPrepareOptionsMenu(menu);


/* We can override onBackPressed method to toggle navigation drawer*/
@Override
public void onBackPressed() 
    if(mDrawerLayout.isDrawerOpen(mDrawerList))
        mDrawerLayout.closeDrawer(mDrawerList);
    else 
        mDrawerLayout.openDrawer(mDrawerList);
    


【问题讨论】:

Item1Activity 不是Fragment。这是一个Activity。我看不到您在代码中使用的任何 Fragment 你应该先初始化按钮然后 setOnItemClickListener 。 【参考方案1】:

按钮定义在哪里?如果它在R.layout.activity_main 中,那么您应该先充气然后尝试找到按钮。更改您的代码:

第一:

getLayoutInflater().inflate(R.layout.activity_main, frameLayout);

第二个:

button1 = (Button) findViewById(R.id.button1);

这应该可以解决问题。

【讨论】:

欢迎您。随意接受答案和/或投票:)

以上是关于片段崩溃与 setOnClickListener的主要内容,如果未能解决你的问题,请参考以下文章

片段中的意图不断与清单崩溃问题,android studio

片段未与片段管理器关联。 (对话片段)

Android - 应用程序启动时片段 onCreate 崩溃

Fragment 与 Parcel 一起崩溃:调用 onPause 方法时无法编组值错误

片段在重新加载时崩溃

片段更改崩溃