0

So im quite new to Android Studio and app development in general and i had this issue for a while, with no luck of fixing it. I've figured that someone here might provide some ideas for fixing this.. Issue: The refreshing of ListView on UI thread (as suggested here) does not work for me. Here's the declaration of 'Runnable run' (in MainActivity.java):

        public Runnable run;
        // ...
        run = new Runnable() {
        public void run() {
            ArrayList<String> temp1 = (ArrayList<String>) arrayList_1.clone();

            View v = getLayoutInflater().inflate(R.layout.fragment_main, null);

            lv_1 = (ListView) v.findViewById(R.id.listViewMe);

            lv_1.setAdapter(adapter_1);

            arrayList_1.clear();

            arrayList_1.addAll(temp1);

            adapter_1.notifyDataSetChanged();

            lv_1.invalidateViews();
            lv_1.refreshDrawableState();

            Log.e("gig", "DONE REFRESHING");
        }
    };

I call the method here:

@Override
public boolean onNavigationItemSelected(MenuItem item)
{
    int id = item.getItemId();

    Fragment fragment = null;

    if (id == R.id.nav_main) {
        fragment = new FragmentMain();
    } if (id == R.id.nav_history) {
        fragment = new FragmentHistory();
    }

    if (fragment != null)
    {
        FragmentTransaction localFragmentTransaction = getSupportFragmentManager().beginTransaction();
        localFragmentTransaction.replace(R.id.screen_area, fragment);
        localFragmentTransaction.commit();

        runOnUiThread(run); // here
    }

    ((DrawerLayout) findViewById(R.id.drawer_layout)).closeDrawer(GravityCompat.START);
    return true;
}

Now for the part that's confusing me: it works when i add a new item to the ListView via this method:

public void addDebtToOther(String name, String money)
{
    String full = name + ", " + money + " EUR";

    lv_1 = (ListView) findViewById(R.id.listViewMe);

    if (lv_1!=null) {
        lv_1.setAdapter(adapter_1);

        arrayList_1.add(full);
        adapter_1.notifyDataSetChanged();
    } else {
        Log.e("gig", "ListView error, lv is NULL");
    }
}

That's about it, any help would be really apriciated!

nisser
  • 51
  • 5
  • `onNavigationItemSelected()` already call on main thread you do not need `runOnUiThread`. – ADM Mar 21 '18 at 17:57
  • So i should try replacing `runOnUiThread(run)` with all of `run()`'s contents? – nisser Mar 21 '18 at 18:32
  • Yeah you can call it directly .just put whole code in a method and call it . – ADM Mar 21 '18 at 18:34
  • still no luck.. works perfectly if i add another item to the listview through the `addDebtToOther()` method though. – nisser Mar 21 '18 at 18:43

2 Answers2

0

In the run object, a new View is inflated, but as far as I can tell, it's not being added to the Activity's contentView or any of it's children, so it is just a View somewhere in memory that isn't being rendered onto the screen.

Did you mean to do something like this instead?:

        public Runnable run;
        // ...
        run = new Runnable() {
        public void run() {
            ArrayList<String> temp1 = (ArrayList<String>) arrayList_1.clone();

            // View v = getLayoutInflater().inflate(R.layout.fragment_main, null);
            // lv_1 = (ListView) v.findViewById(R.id.listViewMe);
            lv_1 = (ListView) findViewById(R.id.listViewMe);

            lv_1.setAdapter(adapter_1);

            arrayList_1.clear();

            arrayList_1.addAll(temp1);

            adapter_1.notifyDataSetChanged();

            lv_1.invalidateViews();
            lv_1.refreshDrawableState();

            Log.e("gig", "DONE REFRESHING");
        }
    };
Eric
  • 16,397
  • 8
  • 68
  • 76
  • unfortunately the app crashes when i try this, with the following error message: `java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a null object reference` – nisser Mar 22 '18 at 13:54
  • I am referencing the view in `addDebtToOther()` with `lv_1 = (ListView) findViewById(R.id.listViewMe)`, could this be a problem? (Perhaps you can only reference a ListView once?) @Eric – nisser Mar 22 '18 at 13:59
  • @nisser the error that you got means that `lv_1` == `null` probably because `findViewById` was unable to find the view. it's not a problem that it can be referenced in `addDebtToOther()`. it can be referenced countless times as long as it exists. is the `NullPointerException` happening only when `fragment` == `FragmentHistory` ? – Eric Mar 22 '18 at 17:44
  • no, the exception only occurs when `fragment == FragmentMain`, the `FragmentHistory` one does not crash the app. – nisser Mar 22 '18 at 18:31
  • @nisser it sounds like that there is no `View` with the id `listViewMe` in the layout used by `FragmentMain`. so either a `View` with that id needs to be added to `FragmentMain`, or the logic in `run` should not be executed when `fragment` is a `FragmentMain` – Eric Mar 22 '18 at 18:47
  • my `fragment_main.xml` file has the `listViewMe` ListView, i checked. Problem with your second suggestion is that i need `run` to execute when i switch to the `FragmentMain` fragment. – nisser Mar 22 '18 at 19:13
  • it seems pretty odd that it works when `fragment` is a `FragmentHistory`, and throws an `NPE` when `fragment` is a `FragmentMain`... are these `Fragment*` classes inflating the right layouts? – Eric Mar 22 '18 at 19:19
  • looks like it: `layoutInflater.inflate(R.layout.fragment_main, null);` ... Perhaps it has something to do with the `null` root passed as parameter to the `.inflate`? – nisser Mar 22 '18 at 19:56
  • oh, i think i know why... [`commit()`](https://developer.android.com/reference/android/app/FragmentTransaction.html#commit()) doesnt add the fragment to the `Activity` immediately. that's very tricky. i think a quick fix would be to run the whole statement `runOnUiThread(run);` from a different `Thread`. a more proper fix would be to execute `run` in `Fragment.onStart()`. this might be useful to you too: https://stackoverflow.com/questions/6495898/findviewbyid-in-fragment – Eric Mar 22 '18 at 20:14
  • Alright, i'll try this and report the results in 24 hours, hopefully this is the issue i'm facing here. – nisser Mar 22 '18 at 20:20
0

Ok so after about a week of head-banging, with the help of @Eric i've figured it out. Turns out i needed to call the run() method in my fragment's .onStart(), like this:

    @Override
    public void onStart() {
    super.onStart();

    ((MainActivity)getContext()).run.run();
    }

Thanks again Eric!

nisser
  • 51
  • 5