3

In my android app I have a spinner that I initialize with some categories

public void loadData()
{
    Thread t=new Thread(new Runnable()
    {
        @Override
        public void run()
        {
            try
            {
                String link="http://"+Static.host+"/allcategories/?format=json";
                String json="";
                URL url = new URL(link);
                BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
                String line;
                while ((line = in.readLine()) != null)
                {
                    json += line;
                }
                in.close();
                JSONArray elements=new JSONArray(json);
                for (int i = 0; i < elements.length(); i++)
                {
                    JSONObject category=elements.getJSONObject(i);
                    spinnerArray.add(category.getString("title"));
                }
                runOnUiThread(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        spinnerAdapter.notifyDataSetChanged();
                    }
                });
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
        }
    });
    t.start();
    try
    {
        t.join();
    }
    catch (Exception e)
    {
        Toast.makeText(MainActivity.this,e.getMessage(),Toast.LENGTH_LONG).show();
    }
}

I created a function that will search articles based on the selected category

public void getArticlesByCategory(String category)
{
    // I search articles and I display them in a listview
}

Then I created an event listener for the spinner

spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
{
    @Override
    public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id)
    {
        getArticlesByCategory(spinner.getSelectedItem().toString());
    }
    @Override
    public void onNothingSelected(AdapterView<?> adapterView)
    {
    }
});

Finally I call loadData in onCreate

loadData();

The problem is that the event is triggered in the initialization of the spinner, which causes getArticlesByCategory to be called every time a new element is added.

I would like to know how I can trigger the event only when I manually select from the spinner.

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Amine Messaoudi
  • 2,141
  • 2
  • 20
  • 37

2 Answers2

1

This appened to me also a couple of times, try calling your loadData() method before adding the setOnItemSelectedListener(...)

This will add the items before the event listener is set and will not trigger it

Hope this helps

Edit from comment

If you populate a list in an async thread, it goes on the background thread and 99% it will finish after the listener is instantiated.

So, if you want to populate after the async thread, add the listener initialization in your thread after the item's loading using context.RunOnUiThread(...) (or better, use AsyncTask)

IE: instantiate the listener where you call spinnerAdapter.notifyDataSetChanged(); in loadData()

Edit number 2

Ok, you have two possibilities at this point, I don't know why it doesn't work the above for you.

  1. Add a check for lastSelectedItem != newSelectedItem and if true, run your code inside the listener, if it is false, the selected item is not changing and you can skip the event.

  2. Watch this SO post and add the listener as explained

Community
  • 1
  • 1
Pier Giorgio Misley
  • 5,305
  • 4
  • 27
  • 66
  • I have already done it but the same problem happens. I'm using a thread to populate categories and when I removed the code from the thread the event didn't trigger but the categories aren't added – Amine Messaoudi Jun 18 '18 at 15:52
  • @AmineMessaoudi I added a comment on "how to use it async" in my answer. You can still load it asynchronously if you want, there are no need to block ui thread :) – Pier Giorgio Misley Jun 18 '18 at 15:57
  • I instanciated the listener after spinnerAdapter.notifyDataSetChanged(); but it still triggering – Amine Messaoudi Jun 18 '18 at 16:05
  • @AmineMessaoudi where do you call the `spinner.setItemSource(spinnerArray)`? (or how it is, i got no compiler atm) – Pier Giorgio Misley Jun 18 '18 at 16:12
  • In onCreated I call this : spinnerAdapter = new ArrayAdapter(getBaseContext(),android.R.layout.simple_spinner_dropdown_item, spinnerArray);adapter = new ArticleAdapter(getBaseContext(),R.layout.article, articles);spinner.setAdapter(spinnerAdapter); – Amine Messaoudi Jun 18 '18 at 16:17
  • @AmineMessaoudi I don't know why it doesn't work for you honestly, there are two workaround that comes in my mind actuallym I added those to the answer – Pier Giorgio Misley Jun 18 '18 at 16:22
1

I would expected the solution above to work but if it doesn't a simple boolean flag would allow you to detect when the items are loaded.

1.Create a boolean isDataLoaded = false;

2.Add a condition in your onItemSelected listener

if (isDataLoaded) { //sort categories };

3.When the data loaded just set the boolean to true;

Rainmaker
  • 10,294
  • 9
  • 54
  • 89