How to set data correctly in Lisview?

1

Well, I'm getting a lot of asynchronous request on Android. I am requesting a list of states in JSON , via OkHttp , and transforming into ArrayList states to be able to set states in ListView . However, in all the ways I tried the request it only ends after the creation of Fragment , so the ArrayList that I set as the adapter parameter to execute setListAdapter is empty. That way, it always generates NullPointerException and I'm not sure what to do.

I will leave below my last code, which I have already taken from an example here from the stack, but I did not get a positive result.

How do I receive the request correctly? If Synchronous the app will get stuck and I believe that it should have a legal way of doing.

Follow the code. (obs: I use an interface to help in logic, it was the idea I saw here in the stack)

Fragment of the list of states

public class PesquisaEstado extends ListFragment implements AsyncResponse {

    private ArrayList<Estado> estados;
    private ArrayAdapter<Estado> mAdapter;

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

        new EstadosTask(this).execute();

        mAdapter = new ArrayAdapter<>(getActivity(),
                R.layout.item_list_pesquisa, estados);
        setListAdapter(mAdapter);

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public void processFinish(ArrayList<Estado> estados) {
        this.estados = estados;
    }
}

Class that extends AsyncTask

public class EstadosTask extends AsyncTask<Void, Void, ArrayList<Estado>>{

    public static final String URL =
            "https://bitbucket.org/Jocsa/jsonauxiliaresotb/raw/1fa827f1179ee827d1bedcdaa4c5befbe7686057/Estados.json";

    public AsyncResponse delegate = null;

    public EstadosTask(AsyncResponse delegate){
        this.delegate = delegate;
    }

    @Override
    protected ArrayList<Estado> doInBackground(Void... params) {
        OkHttpClient client = new OkHttpClient();
        client.setReadTimeout(10, TimeUnit.SECONDS);
        client.setConnectTimeout(15, TimeUnit.SECONDS);

        Request request = new Request.Builder().url(URL).build();
        try {
            Response response = client.newCall(request).execute();
            Type listType = new TypeToken<ArrayList<Estado>>(){}.getType();
            String json = response.body().string();
            Gson gson = new Gson();
            ArrayList<Estado> estados = gson.fromJson(json, listType);
            return estados;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPostExecute(ArrayList<Estado> estados) {
        delegate.processFinish(estados);
    }
}

Interface that I created (based on an example here of the stack)

public interface AsyncResponse {


  void processFinish(ArrayList<Estado> estados);
}

Ps: I've done a light debug and the processFinish() method in PesquisaEstado only runs after onActivityCreated() , so the state is empty and gives NullPointerException .

Thanks in advance for any help!

    
asked by anonymous 18.10.2016 / 03:01

2 answers

2

Some things you will have to change. At first it is not legal to instantiate objects without storing them like this: new EstadosTask(this).execute();

The garbage collector often gets very angry at such things, especially asynchronous.

Another thing, if you want to use this type of adapter, it's cool that you try to implement your own BaseAdapter , so you can call whatever interface format you want during the listing. Ex: Images, TextView, etc.

This NullPointerException is rolling because of the Array states that was not instantiated, to initialize the adapter you can create with it empty, but have to instantiate. Set the beginning more or less like this:

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

    estados = new ArrayList<Estado>();

    mAdapter = new ArrayAdapter<>(getActivity(),
            R.layout.item_list_pesquisa, estados);
    setListAdapter(mAdapter);

    //Isso tem que ficar no final, pois corre o risco de finalizar antes.
    EstadosTask estadosTask = new EstadosTask(this).execute();

}

Another thing is this method processFinish() in it you have to setar the data in your adapter, otherwise it will not update. It would look something like this:

@Override
public void processFinish(ArrayList<Estado> estados) {
    mAdapter.addAll(estados);
}

This topic has some nice examples to follow! link

    
18.10.2016 / 03:27
1

You are giving null pointer because you create adapter while asynktask is doing the data request (it executes in parallel to the main code, that is, when you set the adapter the code of asynktask is still running).

You first have to execute the asynktask and after the result to create the adapter .

As you know what you are doing and you are using delegate , then in the processFinish method that is in activity (you have implemented the interface AsyncResponse in this activity ) you will create adapter in it.

Flow: executes the Asynk task - on the result result gets the arraylist and sends to the activity via delegate - in the implemented method, it creates the adapter and it directs the data that is in that list that you sent it to activity .

You can even make a favor and before running asynktask you can set the background layout with a loading animation (progressbar) and then in delegate you will see the "normal" layout that contains the lists ( before creating the adapter , pq if it will not give null pointer at the time it fetches the list model in xml).

    
18.10.2016 / 14:25