java.lang.NullPointerException: button returning null

2

Good morning,

How do I reference a button in another activity? In main, I'm using another layout to inflate my list, and the button event is obviously returning null because it's not finding the view. Help.

private static String pesquisarDadosLivro;
private DadosLivrosAdapter adapter;

private static final String GOOGLE_LIVROS_URL =
        "https://www.googleapis.com/books/v1/volumes?q=  " + pesquisarDadosLivro;

private static final int DADOSLIVROS_ID_LOADER = 1;

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

    Button pesquisarLivro = (Button) findViewById(R.id.pesquisar);
    pesquisarLivro.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            EditText dadosLivro = (EditText) findViewById(R.id.dados_livro);
            pesquisarDadosLivro = dadosLivro.getText().toString();
            //Log.v("MainActivity", "Texto a ser pesquisado " + pesquisarDadosLivro);
        }
    });

    ListView listView = (ListView) findViewById(R.id.lista);
    adapter = new DadosLivrosAdapter(this, new ArrayList<DadosLivro>());
    listView.setAdapter(adapter);

    LoaderManager loaderManager = getLoaderManager();
    loaderManager.initLoader(DADOSLIVROS_ID_LOADER, null, this);
}

@Override
public android.content.Loader<List<DadosLivro>> onCreateLoader(int i, Bundle bundle) {
    // Create a new loader for the given URL
    return new DadosLivrosLoader(this, GOOGLE_LIVROS_URL);
}

@Override
public void onLoadFinished(android.content.Loader<List<DadosLivro>> loader, List<DadosLivro>
        informacoesLivros) {

    if (informacoesLivros != null && !informacoesLivros.isEmpty()) {
        adapter.addAll(informacoesLivros);
    }
}

@Override
public void onLoaderReset(android.content.Loader<List<DadosLivro>> loader) {
    adapter.clear();
}

}

Hello, I solved the problem by inflating the main activity itself, as it contains the components that interact with the user and it is only 1 single screen, I found it more viable, however I am with another error, my http request returned 400, I need the Loader to be loaded after the button event, do you know how I can do this?

package com.example.android.listadelivros;
import android.app.LoaderManager;
import android.app.LoaderManager.LoaderCallbacks;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity
        implements LoaderCallbacks<List<DadosLivro>> {

    private String pesquisarDadosLivro;
    private DadosLivrosAdapter mAdapter;

    private  String GOOGLE_LIVROS_URL = null;

    private static final int DADOSLIVROS_ID_LOADER = 1;

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

        final Button pesquisarLivro = (Button) findViewById(R.id.pesquisar);
        pesquisarLivro.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                EditText dadosLivro = (EditText) findViewById(R.id.dados_livro);
                pesquisarDadosLivro = dadosLivro.getText().toString();
                GOOGLE_LIVROS_URL =
                        "https://www.googleapis.com/books/v1/volumes?q= " + pesquisarDadosLivro;

                final LoaderManager loaderManager = getLoaderManager();
                loaderManager.initLoader(DADOSLIVROS_ID_LOADER, null,);

            }
        });

        ListView listView = (ListView) findViewById(R.id.lista);

        mAdapter = new DadosLivrosAdapter(this, new ArrayList<DadosLivro>());

        listView.setAdapter(mAdapter);

    }

    @Override
    public android.content.Loader<List<DadosLivro>> onCreateLoader(int i, Bundle bundle) {

        return new DadosLivrosLoader(this, GOOGLE_LIVROS_URL);
    }

    @Override
    public void onLoadFinished(android.content.Loader<List<DadosLivro>> loader, List<DadosLivro>
            informacoesLivros) {

        if (informacoesLivros != null && !informacoesLivros.isEmpty()) {
            mAdapter.addAll(informacoesLivros);
        }
    }

    @Override
    public void onLoaderReset(android.content.Loader<List<DadosLivro>> loader) {
        mAdapter.clear();
    }
}
    
asked by anonymous 04.05.2017 / 17:33

1 answer

1

Hello, Aline

What you intend to do unfortunately is not possible. A View only exists after an Activity inflates it (instantiate, make exist ...) through the setContentView(int layout) method and starts to manipulate it. A Activity can not handle View of another Activity anyway.

I have two possible solutions, and that choice will depend on how your project is as a whole.

1- Work with Fragments and have the interactions in the snippet sent to Activity to manipulate it.

To begin with, the idea is that your Activity implements an interface that Fragment knows and calls. So let's create the interface that will be called when there was a click on the fragment:

public interface OnFragmentButtonClickListener  {
    public void onButtonClick();
}

Then let's make Activity inherit from this interface and implement the method:

public class MinhaActivity extends AppCompact implements OnFragmentButtonClickListener {

    //... Outros métodos comuns da Activity

    public void onButtonClick() {
       //O botão do fragment foi clicado, faça o que tem que fazer na activity!
    }

}

Right, in the onAttach() method of your fragment, which is called during the fragment lifecycle when a fragment is appended to Activity , capture Activity using polymorphism for terms in hands an instance of% with%. This way:

public void FragmentTwo extends Fragment {

   OnFragmentButtonClickListener onFragmentButtonClickListener

   @Override
    public void onAttach(Context context) {
        if(context instanceof OnFragmentButtonClickListener) {
            onFragmentButtonClickListener = (OnFragmentButtonClickListener) context;
        }
        super.onAttach(context);
    }

    //Métodos comuns ao fragment
}

Now, in the OnFragmentButtonClickListener of your button call the interface that is implemented by onClickListener so that Activity can match the click on the fragment:

fragmentButton.setOnClickListener(new OnClickListener() {
    public void onClick(View v) {
       //onFragmentButtonClickListener.onButtonClick(); Lembrando que onFragmentButtonClickListener pode ser null caso a activity não implemente a interface.
    } 
});

2- An Activity transfer event to another Activity through Activity .

What happens is that an Activity B is opened by Activity A, which is waiting for some return from Activity B. Activity B only exists for interactions to occur and thus ends its life cycle by returning something to Activity A. What we can do is to make Activity A open Activity B and, when the X button is clicked, end the life of Activity B by returning Activity A to an indication that the button was clicked. I do not know if this fits into the design context you have and I do not think it's an elegant solution , but come on.

In Activity A, you will open Activity B not through the startActivityForResult(Intent intent, int FLAG) method, but through startActivitiy(Intent intent) .

When you start ActivityB, we inform you the return flag:

Intent intent = new Intent(this, ActivityB.class);
int flagRetorno = 55;
startActivityForResult(intent, flagRetorno);

When you click on the Activity B button, we can inform you to save it in some way that it was clicked and, when we finish Activity B, we can inform Activity A that it has been clicked like this:

Intent returnIntent = new Intent();
returnIntent.putExtra("botaoclicado", true);
setResult(Activity.RESULT_OK, returnIntent);
finish();

But how do I get this in Activity A? By the startActivityForResult(Intent, FLAG) method that is part of the onActivityResult(int requestCode, int resultCode, Intent data) life cycle.

@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
     if (requestCode == flagRetorno) { 
        if(resultCode == Activity.RESULT_OK){
             boolean botaoFoiClicado = data.getStringExtra("botaoclicado");
         }
     }
}

I reaffirm that I do not believe that it is the most elegant and even functional solution for your case , but it is something to think about and suddenly be used if you better analyze your project structure.

Att,

    
05.05.2017 / 14:38