如何修复 getActionBar 方法可能会产生 java.lang.NullPointerException

Posted

技术标签:

【中文标题】如何修复 getActionBar 方法可能会产生 java.lang.NullPointerException【英文标题】:How to fix getActionBar method may produce java.lang.NullPointerException 【发布时间】:2015-06-29 10:17:44 【问题描述】:

我在活动中使用工具栏作为我的操作栏。我正在尝试将 getActionBar().setDisplayHomeAsUpEnabled(true); 方法添加到 Activity.java 文件中,以便为旧设备提供向上导航。

该方法在 android Studio 中产生以下错误消息:

方法调用可能产生 java.lang.NullPointerException

工具栏上的向上导航在较新的设备上运行良好...现在我正在尝试弄清楚如何确保它适用于较旧的设备。 请指教。

来自 build.gradle:

dependencies 
   compile "com.android.support:appcompat-v7:22.1.0"

来自 AndroidManifest.xml:

android:theme="@style/Theme.AppCompat.NoActionBar.FullScreen" 

来自styles.xml

<style name="Theme.AppCompat.NoActionBar.FullScreen" parent="AppTheme">
<item name="android:windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="android:windowFullscreen">true</item>

来自 Activity.java

public class CardViewActivity extends AppCompatActivity 

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

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);

    if (toolbar != null) 
        // Up navigation to the parent activity for 4.0 and earlier
        getActionBar().setDisplayHomeAsUpEnabled(true);
        toolbar.setNavigationIcon(R.drawable.ic_action_previous_item);
        toolbar.setNavigationOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                onBackPressed();
            
        );
    


【问题讨论】:

你的主题不是没有ActionBar吗? 【参考方案1】:

实际上,Android Studio 并没有向您显示“错误消息”,它只是一个警告。

一些答案​​建议使用断言,Dalvik 运行时默认关闭assertion,因此您必须实际打开它才能实际执行某些操作。在这种情况下(断言已关闭),您实际上所做的只是欺骗 Android Studio 不向您显示警告。另外,我不喜欢在生产代码中使用“断言”。

在我看来,你应该做的很简单。

if(getActionBar() != null)
   getActionBar().setDisplayHomeAsUpEnabled(true);

更新: 如果您使用的是操作栏的支持库版本,则应将 getActionBar() 替换为 getSupportActionBar()。

if(getSupportActionBar() != null)
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

【讨论】:

虽然我最初使用 assert 来“解决”警告,但我同意您推荐的代码比 assert hack 更好。答案已被赞成并接受。请注意,我使用 AppCompatActivity 作为一个类,所以我必须在我的解决方案中使用 getSupportActionBar() 而不是上面显示的 getActionBar()。 为什么 android studio 不对 getSupportActionBar().setTitle() 等其他方法发出相同的警告? 我正在使用 getSupportActionBar() != null 但我的工具栏上仍然出现空指针。有谁知道发生了什么?我已经尝试过断言行,它也只是抛出一个空指针!??!这是怎么回事!??!?!?! @ZooMagic 它可能抛出 NPE 的原因有很多。我建议您搜索与您的问题相似的其他问题或将您的代码发布在新问题上。您需要共享您的布局文件、清单和 Activity 代码。【参考方案2】:

首先,您需要将工具栏设置为支持ActionBar。 然后,如果您确定它会一直存在,只需将其声明为!= null。这将告诉编译器它不会为空,因此空检查通过。

@Override
protected void onCreate(Bundle savedInstanceState)

   super.onCreate(savedInstanceState);
   setContentView(R.layout.cardviewinput);

   Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
   setSupportActionBar(toolbar);

   assert getSupportActionBar() != null;
   getSupportActionBar().setDisplayHomeAsUpEnabled(true); // it's getSupportActionBar() if you're using AppCompatActivity, not getActionBar()

【讨论】:

好的,看起来不错,但断言行在 Android Studio 中生成“无法解析符号 'getSupportActionBar'”错误。应该是“getSupportActionBar()”吗?请指教。 扩展AppCompatActivity或FragmentActivity时只能访问getSupportActionBar【参考方案3】:

感谢安德鲁的回答。 如果你有一个导航抽屉或其他使用 getSupportActionBar() 的东西,你需要添加 assert getSupportActionBar() != null;

和平,

例子:

@Override
public void setTitle(CharSequence title) 
    mTitle = title;
    assert getSupportActionBar() != null;
    getSupportActionBar().setTitle(mTitle);

【讨论】:

这对生产有效还是仅对测试有效? gian1200 我不确定。一个好问题。我计划很快发布我的应用程序,所以在发布之前我会做一些研究......谢谢。 我的猜测是编译器会将其更改为“如果它为空,则抛出一个 assertExeption”;不允许您处理错误。【参考方案4】:

试试这个:

private ActionBar getActionBar() 
    return ((AppCompatActivity) getActivity()).getSupportActionBar();

【讨论】:

【参考方案5】:

我所做的是在我的基本 Activity 中覆盖 getSupportActionBar() 方法并添加 @NonNull 注释。这样,我只会在基本活动中收到一个关于我如何将 @NonNull 注释用于具有 @Nullable 注释的东西的 lint 警告。

    @NonNull
    @Override
    public ActionBar getSupportActionBar() 
        // Small hack here so that Lint does not warn me in every single activity about null
        // action bar
        return super.getSupportActionBar();
    

【讨论】:

感谢您的回答。我不知道如何使用 lint。您能否评论一下您的答案与上面的 Adam Ghani 的答案相比有什么优势? 使用 Adam 的方法,您必须在所有活动中编写 if 语句。使用我的方法,您只需覆盖基本活动中的 getSupportActionBar,其余代码保持原样。【参考方案6】:

我创建了一个通用类,例如:

public final class Cast

    private Cast() 

    /**
     * Helps to eliminate annoying NullPointerException lint warning.
     */
    @android.support.annotation.NonNull
    public static <T> T neverNull(T value)
    
        return value;
    

然后我可以将它用于任何带有 NullPointerException 警告的调用,我确信它永远不会发生,例如

final ActionBar actionBar = Cast.neverNull(getSupportActionBar());
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);

附:不要忘记将“com.android.support:support-annotations”添加到您的 gradle 文件中。

【讨论】:

【参考方案7】:

getSupportActionBar().setDisplayHomeAsUpEnabled(true);之前添加assert getSupportActionBar() != null;

【讨论】:

【参考方案8】:
 if(actionBar != null) 
  actionBar.setHomeButtonEnabled(true);
  actionBar.setBackgroundDrawable(ContextCompat.getDrawable(mContext,
                                  R.drawable.action_bar_gradient));
 

【讨论】:

【参考方案9】:

使用这个主题:android:theme="@style/Theme.AppCompat.Light.NoActionBar"

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle("Title");
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
actionBar.setHomeButtonEnabled(true);
actionBar.setHomeAsUpIndicator(R.drawable.ic_action_previous_item);
actionBar.setDisplayHomeAsUpEnabled(true);

【讨论】:

【参考方案10】:

或者,您可以将操作栏断言为不为空。在调用您的操作栏之前添加断言,如下所示

assert getSupportActionBar() != null;

因此,最终的 sn-p 如下所示:

    setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
    assert getSupportActionBar() != null;
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

【讨论】:

【参考方案11】:

试试这个:

setSupportActionBar (toolbar);
if(getSupportActionBar () != null) 
assert getSupportActionBar () != null;
getSupportActionBar ().setDisplayHomeUpEnabled(true);

注意 setSupportActionBar(toolbar) 应该在 getSupportActionBar() 之前。

【讨论】:

【参考方案12】:
  if(getSupportActionBar() != null)
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    
    OR

MainActivity extends AppCompatActivity 替换为public class MainActivity extends AppCompatActivity

【讨论】:

【参考方案13】:

只需检查 getSupportActionBar 不等于 null

    setSupportActionBar(toolbar);

    if(getSupportActionBar() != null) 
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setTitle("Daily Shopping List");
    

【讨论】:

【参考方案14】:

如果你正在导入

android.app.ActionBar 

你必须使用 getActionBar()

如果你正在进口

android.support.v7.app.ActionBar

使用 getSupportActionBar()

【讨论】:

以上是关于如何修复 getActionBar 方法可能会产生 java.lang.NullPointerException的主要内容,如果未能解决你的问题,请参考以下文章

IntelliJ 检查:“方法调用可能会产生 NullPointerException”。建议的修复有意义吗?

Java -- 每日一问:什么情况下Java程序会产生死锁?如何定位修复?

getActionBar() 返回 null

如何找到并修复崩溃的原因

getActionBar()为null的解决方法总结(引用他人)

DLL是啥文件?丢失会出现啥后果和如何修复?