首页 > 解决方案 > 尝试更改片段背景时出现 NullPointerException(空对象引用上的 setBackgroundResource)

问题描述

所以我花了几个小时在这里翻阅帖子并尝试各种解决方案,但我真的无法弄清楚为什么每当我尝试更改 QuotesFragment 的背景时应用程序就会崩溃。基本上,在 SettingsFragment 中,用户从微调器中选择一个主题,内部类获取值并使用接口将值传递给 QuotesFragment,这将改变其背景。

我原本想从 SettingsFragment 更改它,但这似乎更令人头疼。我真的只想改变特定片段的背景,而不是每个片段。我最初有一个 QuotesFragment 的相对布局并试图改变它,但我在网上看到的一个建议是为背景嵌套一个 RelativeLayout。

几乎每当我单击 SettingsFragment 中的“保存”按钮时,应用程序就会崩溃。在尝试实施背景更改之前一切正常,所以我觉得这与此有关。任何帮助将不胜感激。另外,我在这里发帖的经验不多,如果这不是应有的方式,我很抱歉。


public class SettingsFragment extends Fragment implements AdapterView.OnItemSelectedListener {

    private Switch notificationSwitch;
    private TextView notificationsTV;
    private TextView perDayTV;
    private Button saveButton;
    private Button clearButton;

    ArrayList<Calendar> calList;

    Spinner quotesSpinner;
    Spinner themesSpinner;

    private int QUOTES_SPINNER_VALUE;
    private String THEMES_SPINNER_VALUE;

    public interface BackgroundThemeListener{
        void themeSelected(String theme);
    }//interface

    private BackgroundThemeListener bgListener;


    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.settings_fragment, container, false);
        getActivity().setTitle("Settings");

        THEMES_SPINNER_VALUE = "";
        QUOTES_SPINNER_VALUE = 0;

        notificationSwitch = view.findViewById(R.id.notification_switch);
        notificationsTV = view.findViewById(R.id.notifications_onoff_textview);
        perDayTV = view.findViewById(R.id.per_day_textview);
        saveButton = view.findViewById(R.id.save_button);
        clearButton = view.findViewById(R.id.clear_button);

        calList = new ArrayList<>();

        quotesSpinner = view.findViewById(R.id.per_day_spinner);
        ArrayAdapter<CharSequence> quotesAdapter = ArrayAdapter.createFromResource(getContext(), R.array.quotes_per_day_numbers, android.R.layout.simple_spinner_item);
        quotesAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        quotesSpinner.setAdapter(quotesAdapter);
        quotesSpinner.setOnItemSelectedListener(this);

        themesSpinner = view.findViewById(R.id.themes_spinner);
        ArrayAdapter<CharSequence> themeAdapter = ArrayAdapter.createFromResource(getContext(), R.array.bg_themes, android.R.layout.simple_spinner_item);
        themeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        themesSpinner.setAdapter(themeAdapter);
        themesSpinner.setOnItemSelectedListener(new ThemesSpinnerClass());

        notificationSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if(isChecked){
                    perDayTV.setVisibility(View.VISIBLE);
                    quotesSpinner.setVisibility(View.VISIBLE);
                    saveButton.setVisibility(View.VISIBLE);
                    clearButton.setVisibility(View.VISIBLE);
                    Toast.makeText(getActivity(), "Notifications On", Toast.LENGTH_SHORT);
                } else{
                    perDayTV.setVisibility(View.INVISIBLE);
                    quotesSpinner.setVisibility(View.INVISIBLE);
                    saveButton.setVisibility(View.INVISIBLE);
                    clearButton.setVisibility(View.INVISIBLE);
                    Toast.makeText(getActivity(), "Notifications Cleared", Toast.LENGTH_SHORT);
                }//if/else
            }//onCheckChanged
        });

        saveButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                bgListener.themeSelected(THEMES_SPINNER_VALUE);

                int hour;
                int minute;

                //for loop adding calendars to the list
                for (int i = 0; i < QUOTES_SPINNER_VALUE; i++){
                    Calendar cal = Calendar.getInstance();
                    hour = (int) (Math.random() % 24) + 1;
                    minute = (int) (Math.random() % 60) + 1;

                    cal.set(Calendar.HOUR_OF_DAY, hour);
                    cal.set(Calendar.MINUTE, minute);
                    cal.set(Calendar.SECOND, 0);
                    calList.add(cal);
                }//for

                Toast.makeText(getActivity(), "Times Set Randomly", Toast.LENGTH_SHORT).show();
                startAlarm();
                bgListener.themeSelected(THEMES_SPINNER_VALUE);
            }//onClick
        });

        clearButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                for (Calendar cal : calList) {
                    cancelAlarm();
                }//for

                Toast.makeText(getActivity(), "Notifications Cleared", Toast.LENGTH_SHORT).show();
            }
        });

        return view;
    }//onCreateView method


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

        QUOTES_SPINNER_VALUE = Integer.parseInt(quotesSpinner.getSelectedItem().toString());

    }//onItemSelected method

    @Override
    public void onNothingSelected(AdapterView<?> parent) {

    }//onNothingSelected method

    private void startAlarm(){
        for (Calendar cal : calList) {
            AlarmManager alarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);

            Intent intent = new Intent(getActivity(), AlertReceiver.class);
            PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivity(), 1, intent, 0);
            alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmManager.INTERVAL_DAY, pendingIntent);
        }//for
    }//startAlarm method

    private void cancelAlarm(){
            AlarmManager alarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);

            Intent intent = new Intent(getActivity(), AlertReceiver.class);
            PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivity(), 1, intent, 0);
            alarmManager.cancel(pendingIntent);
    }//cancelAlarm method


    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if(context instanceof BackgroundThemeListener){
            bgListener = (BackgroundThemeListener) context;
        }//if
        else{
            throw new RuntimeException(context.toString() + " must implement BackgroundThemeListener");
        }//else
    }//onAttach method

    @Override
    public void onDetach() {
        super.onDetach();
        bgListener = null;
    }//onDetach method



    class ThemesSpinnerClass implements AdapterView.OnItemSelectedListener{


        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            THEMES_SPINNER_VALUE = themesSpinner.getItemAtPosition(position).toString();
            //bgListener.themeSelected(THEMES_SPINNER_VALUE);
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {

        }
    }//ThemesSpinnerClass

}//SettingsFragment class






import static com.abc.danielharrington.betterdays.BetterDays.CHANNEL_1_ID;
import static com.abc.danielharrington.betterdays.BetterDays.CHANNEL_2_ID;

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, SettingsFragment.BackgroundThemeListener {

    private DrawerLayout drawer;
    private NotificationManagerCompat notificationManager;
    private QuotesFragment quotesFragment;
    private AboutFragment aboutFragment;
    private SettingsFragment settingsFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        quotesFragment = new QuotesFragment();
        aboutFragment = new AboutFragment();
        settingsFragment = new SettingsFragment();

        notificationManager = NotificationManagerCompat.from(this);

        setContentView(R.layout.activity_main);

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

        drawer = findViewById(R.id.drawer_layout);

        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.addDrawerListener(toggle);
        toggle.syncState();

        NavigationView navView = findViewById(R.id.nav_view);
        navView.setNavigationItemSelectedListener(this);

        if(savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new QuotesFragment()).commit();
            navView.setCheckedItem(R.id.nav_quotes);
        }//if


    }//onCreate method

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()){
            case R.id.nav_quotes:
                getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, quotesFragment).commit();
                break;
            case R.id.nav_about:
                getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, aboutFragment).commit();
                break;
            case R.id.nav_settings:
                getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, settingsFragment).commit();
                break;
            case R.id.nav_share:

                break;

        }//switch

        drawer.closeDrawer(GravityCompat.START);
        return true;
    }



    @Override
    public void onBackPressed(){
        if(drawer.isDrawerOpen(GravityCompat.START)){
            drawer.closeDrawer(GravityCompat.START);

        }else {
            super.onBackPressed();
        }
    }//onBackPressed

    public void sendOnChannel1(View view){
        String title = "Better Days";
        String message = "New Quote Available";

        Notification notification = new NotificationCompat.Builder(this, CHANNEL_1_ID)
                .setSmallIcon(R.drawable.ic_quotes)
                .setContentTitle(title).setContentText(message)
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                .setCategory(NotificationCompat.CATEGORY_MESSAGE)
                .build();

        notificationManager.notify(1, notification);

    }//sendOnChannel1 method

    public void sendOnChannel2(View view){
        String title = "Better Days";
        String message = "New Quote Available";

        Notification notification = new NotificationCompat.Builder(this, CHANNEL_2_ID)
                .setSmallIcon(R.drawable.ic_quotes)
                .setContentTitle(title)
                .setContentText(message)
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                .setCategory(NotificationCompat.CATEGORY_MESSAGE)
                .build();

        notificationManager.notify(2, notification);

    }//sendOnChannel2 method


    @Override
    public void themeSelected(String theme) {
        quotesFragment.updateTheme(theme);
    }//themeSelected
}//MainActivity class






public class QuotesFragment extends Fragment {


    private DrawerLayout drawer;
    private RelativeLayout quotesLayout;
    private String BG_THEME;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.quotes_fragment, container, false);

        getActivity().setTitle("Quotes");

        quotesLayout = rootView.findViewById(R.id.quotes_bg_layout);
        //quotesLayout.setBackgroundResource(R.drawable.img_forest);

        return rootView;
    }//onCreateView method

    public void updateTheme(String theme){
        BG_THEME = theme;

        if (theme.equals("Forest")){
            quotesLayout.setBackgroundResource(R.drawable.img_forest);
        }
        //setQuotesBackground();
    }//updateTheme method

    //method to change the quotes fragment background based on user preference
    private void setQuotesBackground(){


        if(BG_THEME.equals("Forest")){
            quotesLayout.setBackgroundResource(R.drawable.img_forest);
        }

        /*
        switch(BG_THEME){
            case "Default":
                quotesLayout.setBackgroundColor(getActivity().getResources().getColor(R.color.signBlue));

                break;
            case "Forest":
                quotesLayout.setBackgroundResource(R.drawable.img_forest);
                quotesLayout.invalidate();
                break;
            case "Space":
                quotesLayout.setBackground(getActivity().getResources().getDrawable(R.drawable.img_space));
                break;
            case "Mountain":
                quotesLayout.setBackground(getActivity().getResources().getDrawable(R.drawable.img_mountain));
                break;
            case "Beach":
                quotesLayout.setBackground(getActivity().getResources().getDrawable(R.drawable.img_beach));
                break;
            default:
                quotesLayout.setBackgroundColor(getActivity().getResources().getColor(R.color.signBlue));
                break;
        }//switch
        */

    }//setQuotesBackground method

}//QuotesFragment class

这就是错误所说的:

E/AndroidRuntime:致命异常:主进程:com.abc.danielharrington.betterdays,PID:4744 java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“void android.widget.RelativeLayout.setBackgroundResource(int)”在 com.abc.danielharrington.betterdays.QuotesFragment.updateTheme(QuotesFragment.java:45) 在 com.abc.danielharrington.betterdays.MainActivity.themeSelected(MainActivity.java:131) 在 com.abc.danielharrington.betterdays.SettingsFragment$2。 onClick(SettingsFragment.java:101) 在 android.view.View.performClick(View.java:6597) 在 android.view.View.performClickInternal(View.java:6574) 在 android.view.View.access$3100(View. java:778) 在 android.os.Handler 的 android.view.View$PerformClick.run(View.java:25885)。handleCallback(Handler.java:873) 在 android.os.Handler.dispatchMessage(Handler.java:99) 在 android.os.Looper.loop(Looper.java:193) 在 android.app.ActivityThread.main(ActivityThread.java :6669) 在 java.lang.reflect.Method.invoke(Native Method) 在 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 在 com.android.internal.os.ZygoteInit.main (ZygoteInit.java:858)os.ZygoteInit.main(ZygoteInit.java:858)os.ZygoteInit.main(ZygoteInit.java:858)

标签: javaandroidnullpointerexception

解决方案


推荐阅读