尝试更改片段背景时发生NullPointerException(空对象引用上的setBackgroundResource)

时间:2019-05-16 03:36:08

标签: java android nullpointerexception

因此,我已经花了数小时在这里浏览帖子并尝试各种解决方案,但是我真的不知道为什么每次尝试更改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 / Android运行时:致命异常:主要       流程: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.view.View $ PerformClick.run(View.java:25885)           在android.os.Handler.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(本机方法)           在com.android.internal.os.RuntimeInit $ MethodAndArgsCaller.run(RuntimeInit.java:493)           在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

1 个答案:

答案 0 :(得分:-1)

尝试下面的OnViewCreated方法中的代码。

public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        quotesLayout = view.findViewById(R.id.quotes_bg_layout);
        quotesLayout.setBackgroundResource(R.drawable.img_forest);
    }

如果上面的代码不起作用,这意味着您膨胀了错误的布局或可绘制的img森林与设置为背景(例如png,jpg)不兼容。尝试其他图片。