Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TextView not updating

I have a silly problem updating text in a TextView using a handler class. I'm setting custom Info window in Google Maps.

mMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
            @Override
            public View getInfoWindow(Marker marker) {
                return null;
            }

            @Override
            public View getInfoContents(final Marker marker) {
                //setting marker as final***
                View v = getLayoutInflater().inflate(R.layout.my_layout, null);
                TextView name = (TextView) v.findViewById(R.id.name);


                final TextView status = (TextView) v.findViewById(R.id.status);

                for(MyItem mi : myItems){
                    if(mi.getName().equals(marker.getTitle())){

                        name.setText(mi.getName()); //This one updates normaly

                        Handler handler = new Handler();
                        handler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                //this one sets the text, but doesnt update on UI
                                status.setText("Text"); 

                                //Here I call my update text function
                                updateTv(status, "Text");
                                //Refreshing the window***
                                marker.showInfoWindow();

                            }
                        }, 5000);
                        break;
                    }
                }

                return v;
            }
        });
    }

TextView "name" is updating normally, while "status" TextView is only updating its content and not updating visually on the screen. I've tried invalidating, runOnUiThread(), but nothing seems to work. I know the solution might be really obvious, but I don't see it.

Thank you for your help in advance!

EDIT

Here's how i tried runOnUiThread().

public void updateTv(final TextView tv, final String s){

        runOnUiThread(new Runnable() {
            @Override
            public void run() {

                tv.setText(s);

                tv.invalidate();

            }
        });
    }

My XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Large Text"
        android:id="@+id/name"
        android:layout_gravity="center"
        android:gravity="center_horizontal"
        android:padding="10dp"/>


    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:text="..."
        android:id="@+id/status"
        android:gravity="center_horizontal"/>

</LinearLayout>

SOLUTION

I refreshed my window by calling commands commented and signed with *** in the code above. My thanks goes to "clownba0t"

like image 614
tensa11 Avatar asked Oct 29 '22 17:10

tensa11


2 Answers

So you are trying to update the view after it returned from getInfoContents() and that won't work as its not a live view, see this.

Something that might work is calling:

status.invalidate();
like image 81
Ahmad Sanie Avatar answered Nov 02 '22 23:11

Ahmad Sanie


This came from the fact Android is an OS using messages. So there is a part of the OS which read messages and perform actions according to the order in the message.

Refreshing the text in the TextView is done by this way: when you perform setText() your code prepare a message and send it to the OS to tell him "Please refresh the textView"".

We can simplify the explanation saying you can send 10 letters to a friend, but even if you send the 10 letters at the same time, maybe they will not arrived at the same time...

And here, that's the case: for Android, messages for the User Interface are not "priority" messages. But App Code has a high priority. So when you perform the setText() the message is sent, but the OS don't read it as, after the setText() you perform huge code action. So the OS run your code and only when this huge piece of code is finished, the OS say "Oh, well, maybe I received a letter", he open the letter find "Please refresh the textView" and do it. So... AFTER you huge piece of code.

How to solve that? You must put your huge piece of code in a handler.

  TextView tmp_id_top_msg = (TextView) findViewById(R.id.text_top_clavier);
  tmp_id_top_msg.setText("message to display");

  Handler handler_spend_time;
  handler_spend_time = new Handler();
  handler_spend_time.postDelayed(Call_Huge_Code(), 100);

Then:

public Runnable Call_Huge_Code()
{
    return new Runnable()
    {
        public void run()
        {
            // here your code...
        }
    };
}

This will delay the execution of you code by 100 milliseconds which is not enought to "slow" the process but which is enought for Android to read the "refresh setText" message.

like image 31
Peter Avatar answered Nov 02 '22 22:11

Peter