Is it possible to receive a null object from another fragment on Android?

Asked

Viewed 51 times

1

The problem is this: I have two fragments, the first has a list, which if clicked, sends an object to be edited in fragment B. In fragment A there is also an inclusion button that when clicked opens fragment B to register certain information. The code of fragment A is this:

public class AlarmFragment extends Fragment {
private OnFragmentInteractionListener mListener;
private ListView lista;
FloatingActionButton btnAddAlarme;

public AlarmFragment() {
    // Required empty public constructor
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    final View view = inflater.inflate(R.layout.fragment_alarm, container, false);



    TimerDAO dao = new TimerDAO(getActivity());

    List<Timer> timers = dao.getListaAgendamentos();
    dao.close();

    int layout = android.R.layout.simple_list_item_1;
    ListaAgendamentosCadastradosAdapter adapter = new ListaAgendamentosCadastradosAdapter(timers, layout, getActivity());
    //ArrayAdapter<Timer> adapter = new ArrayAdapter<Timer>(getActivity(), layout, timers);

    lista = (ListView)view.findViewById(R.id.listaAgendamentosCadastrados);

    lista.setAdapter(adapter);

    lista.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            Timer agendamentoClicado = (Timer)parent.getItemAtPosition(position);
            CadastroAlarmFragment cadastroAlarmFragment = new CadastroAlarmFragment();

            Bundle args = new Bundle();
            args.putSerializable("agendamentoSelecionado", agendamentoClicado);
            cadastroAlarmFragment.setArguments(args);

            FragmentManager manager = getFragmentManager();
            manager.beginTransaction().replace(R.id.content_main, cadastroAlarmFragment, cadastroAlarmFragment.getTag()).commit();
        }
    });

    btnAddAlarme = (FloatingActionButton) view.findViewById(R.id.btnAddAlarme);

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

            CadastroAlarmFragment cadastroAlarmFragment = new CadastroAlarmFragment();
            FragmentManager manager = getFragmentManager();
            manager.beginTransaction().replace(
                    R.id.content_main,
                    cadastroAlarmFragment,
                    cadastroAlarmFragment.getTag()
            ).commit();

        }
    });

    return view;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

}

@Override
public void onAttach(Context context) {
    super.onAttach(context);
}

@Override
public void onDetach() {
    super.onDetach();
    mListener = null;
}

public interface OnFragmentInteractionListener {
    void onFragmentInteraction(Uri uri);
}

}

Following the searches on the Internet, I send the already existing object from fragment A to fragment B through a Serializable. When the second fragment is opened, I perform a check to see if what came through serializable is an object to be edited or if I need to register a new one. The code of fragment B is as follows::

    public class CadastroAlarmFragment extends Fragment {

    TextView txt_idAgendamento;
    AlarmManager alarmManager;
    TextClock tcHoraAtual;
    Spinner cbSelecaoValvulaCadastroAgendamento;
    EditText etTempoDeFuncionamentoCadastroAgendamento;
    Button btnSalvaAgendamento;
    ToggleButton btnAtivaAgendamento;
    Long milli;
    String actualTime;
    Boolean clickTime = false;
    Context context;
    PendingIntent pendingIntent;
    int hour, minute;
    String horaMinuto;
    public CadastroAlarmHelper helper;


    public CadastroAlarmFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_cadastro_alarm2, container, false);

        helper = new CadastroAlarmHelper(view);

        tcHoraAtual = (TextClock)view.findViewById(R.id.tcHoraAtual);
        cbSelecaoValvulaCadastroAgendamento = (Spinner)view.findViewById(R.id.cbSelecaoValvulaCadastroAgendamento);
        etTempoDeFuncionamentoCadastroAgendamento = (EditText)view.findViewById(R.id.etTempoDeFuncionamentoCadastroAgendamento);
        btnSalvaAgendamento = (Button)view.findViewById(R.id.btnSalvaAgendamento);
        btnAtivaAgendamento = (ToggleButton)view.findViewById(R.id.btnAtivaAgendamento);
        txt_idAgendamento = (TextView)view.findViewById(R.id.txt_idAgendamento);

        Bundle bundle = getArguments();

        final Timer agendamentoParaSerAlterado = (Timer)bundle.getSerializable("agendamentoSelecionado");
        if(agendamentoParaSerAlterado!= null)
        {
           btnSalvaAgendamento.setText("Salvar Alterações");
           helper.colocaAgendamentoNaTela(agendamentoParaSerAlterado);
           tcHoraAtual.setText(agendamentoParaSerAlterado.getDataHoraInicio());
        }
        else if(agendamentoParaSerAlterado == null){
            tcHoraAtual.setFormat24Hour(getTime());
        }

        this.context = getActivity();
        alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);


        TimePickerFragment timePickerFragment = new TimePickerFragment();
        //Cria a instancia do calendario
        final java.util.Calendar calendar =  timePickerFragment.calendar;

        //Criando Intent pra classe AlarmReceiver
        final Intent intent =  new Intent(this.context, AlarmReceiver.class);


        loadSpinnerData();

        tcHoraAtual.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                clickTime = true;
                DialogFragment newFragment = new TimePickerFragment();
                newFragment.show(getActivity().getFragmentManager(), "TIMEPICKER");
            }
        });


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

                String tempo = etTempoDeFuncionamentoCadastroAgendamento.getText().toString();
                if(tempo.isEmpty()){
                    Toast.makeText(getActivity(), "Digite o tempo de funcionamento!", Toast.LENGTH_SHORT).show();
                }
                else{

                    Timer timer = helper.pegaInfoIrrigacaoCadastro();
                    TimerDAO dao = new TimerDAO(getActivity());

                    if(horaMinuto!=null) {
                        horaMinuto = tcHoraAtual.getText().toString();
                        hour = Integer.parseInt(horaMinuto.substring(0, 2));
                        minute = Integer.parseInt(horaMinuto.substring(3, 5));
                    }

                    else if(agendamentoParaSerAlterado == null)
                    {
                        calendar.set(java.util.Calendar.HOUR_OF_DAY, hour);
                        calendar.set(java.util.Calendar.MINUTE, minute);

                        final int _id = ((int)System.currentTimeMillis())*-1;
                        txt_idAgendamento.setText(String.valueOf(_id));

                        intent.putExtra("extra", "on"+tempo);
                        pendingIntent = PendingIntent.getBroadcast(getActivity(), _id, intent, PendingIntent.FLAG_UPDATE_CURRENT);

                        //Definir o AlarmManager
                        alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);

                        dao.salvaTimer(timer);
                    }
                    else{

                        agendamentoParaSerAlterado.setId(agendamentoParaSerAlterado.getId());
                        dao.alteraTimer(timer);
                        Toast.makeText(getActivity(), "Alterações Salvas!", Toast.LENGTH_SHORT);

                    }
                    dao.close();

                    AlarmFragment alarmFragment = new AlarmFragment();
                    FragmentManager manager = getFragmentManager();
                    manager.beginTransaction().replace(
                            R.id.content_main,
                            alarmFragment,
                            alarmFragment.getTag()
                    ).commit();
                }
            }
        });

        btnAtivaAgendamento.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if(isChecked){

                }
                else {
                    String idAgendamento = (String) txt_idAgendamento.getText();
                    int _idAgendamento = Integer.valueOf(idAgendamento);
                    alarmManager.cancel(PendingIntent.getBroadcast(getActivity(), _idAgendamento, intent, PendingIntent.FLAG_CANCEL_CURRENT));
                    //put extra string into intent
                    //Tells the clock that youpressed "cancelar alarme"
                    intent.putExtra("extra","off");
                    //Para a musica
                    context.sendBroadcast(intent);
                }
            }
        });


        return view;
    }


    @RequiresApi(api = Build.VERSION_CODES.N)
    public String getTime()
    {
        milli = System.currentTimeMillis();
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
        Date result = new Date(milli);
        actualTime = sdf.format(result);
        return actualTime;
    }

    private void loadSpinnerData()
    {
        TimerDAO dao = new TimerDAO(getActivity());
        Cursor servicesCursor = dao.getServicesCursor();

        String[]from = {"nomeValvula"};
        int[] to ={android.R.id.text1};

        SimpleCursorAdapter dataAdapter = new SimpleCursorAdapter(getActivity(), android.R.layout.simple_spinner_dropdown_item, servicesCursor, from, to, 0);

        cbSelecaoValvulaCadastroAgendamento.setAdapter(dataAdapter);

    }


}

However, whenever I click the "new" button on Fragment A, Serializable is not sent, and when fragment B starts, it is checked if it is an object to be edited or if it is a new one. When this happens the system gives me the following error:

 FATAL EXCEPTION: main
 Process: com.example.cabral.irriga, PID: 24858
 java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.Serializable android.os.Bundle.getSerializable(java.lang.String)' on a null object reference
 at com.example.cabral.irriga.CadastroAlarmFragment.onCreateView(CadastroAlarmFragment.java:90)

Which is exactly in the check where I need to know if it is a new one, or if it is to be edited, since Serializable is empty the error happens. So is there any other way for me to accomplish this task? Since in Activities can I send an empty Internet and do the same job tried above? Any other suggestions to solve the case?

  • Try to get your argument like this: final Timer agendamentoParaSerAlterado = (Timer)getActivity().getIntent().getSerializableExtra("agendamentoSelecionado");

  • It worked, man! Thank you very much!

  • I put an answer Rodrigo. Hugs. Good luck!

  • For compilation purposes it worked, but in practice it did not. null Pointer doesn’t happen anymore, but I’m not getting any Intent on fragment B. How to send this input to fragment?

  • Are you debugging? What error is happening now?

  • Yes, I am debugging. What happens now is that the object is not being passed from Fragment A to Fragment B. The snippet: Schedule timePare Changed = Timer)getActivity(). getIntent(). getSerializableExtra("agend mentSelected"); Always receiving Null.

  • Try to pass it off: context.getIntent().putExtra("agendamentoSelecionado", agendamentoClicado) in Fragment A

  • Even creating a context and making it receive this.context inside the fragment constructor A. The compiler presents: Cannot resolve method 'getIntent();'

  • Man, I looked right here and I realized there’s no problem with your serializable. The way it was, it works correctly. Try to notice if by clicking the button, if you are really sent a Timer. Make sure you are able to pick up the item correctly through the getItemAtPosition . I’m suspecting that really nothing is passing. I advise on your fragment B you put a check, for example if (bundle != null)

  • I returned to the initial form, and to the initial problem as well. When it is an existing item the getItemAtPosition works perfectly and the line: final Timer agendamentoParaSerAlterado = (Timer)args.getSerializable("agendamentoSelecionado"); also. The problem is that if I do a check like if(bundle != null) and declare the above line within this if the code stops working because there are methods further down that use the variable agendamentoParaSerAlterado. And if I declare it global, it needs to be final, and being finali can’t assign value to it within the if.

  • Well, I took exactly the part that you send and the part that you receive the data through the serializable and worked perfectly by passing some other object. I think your problem here is something else that has nothing to do with the serializable. Particularly I see no problem you create a global variable and check the bundle is only to know if the problem is in the serializable or problem in the object you are sending. I don’t think I can help much because there is no way to reproduce all code here.

  • 1

    Thank you for the strength, but I solved it as follows: On the Fragment A inclusion button I sent a String on bundle to ensure that it was not null, and in Fragment B I kept my code, only verifying that the object was null. If it is, then register a new one, if the object is filled then edit the object. Anyway, thank you so much for the effort and for the help!

Show 7 more comments
No answers

Browser other questions tagged

You are not signed in. Login or sign up in order to post.