Kristiyan Katsarov Kristiyan Katsarov - 4 months ago 21
Java Question

Android communication between main thread and other thread

I want to change dynamically the text of a textview, but I will need the same logic if I want to make a game thread, so I need to make the communication between the main one and the second one.

I have the files :

MainActivity

public class MainActivity extends ActionBarActivity {

public static Handler mHandler;
Runnable thread = new SampleThread();
TextView txt1 = (TextView) findViewById(R.id.txt1);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActionBar actionBar = getSupportActionBar();
actionBar.hide();

//hiding status bar
if (Build.VERSION.SDK_INT < 16) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
} else {
View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);
}
setContentView(R.layout.activity_main);


mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
// i want to change the text of txt1 here
}
};
new Thread(thread).start();


}
}


SampleThread

package com.example.katsar0v.myapplication;

import android.util.Log;

/**
* Created by Katsar0v on 1/21/2015.
*/
public class SampleThread implements Runnable {

@Override
public void run() {
int two = 0;
while(two<10) {
two++;
try {
Thread.sleep(1000);

//instead of logging, i want to send the text to main UI
Log.d("MSG", String.valueOf(two + "sec"));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}


The problem I see is, how do I change the text with the handler, when my thread is in another file? Or should I make the second class static within the first one (and what should I do when the code gets really long, it can't be all in one file)?

Answer

You could implement a custom Interface in order to handle it from your main activity. On your SampleThread:

public interface TextViewChangeListener
{
    public void onTextViewChanged(String newName);
}
TextViewChangeListener mListener;

Then call mListener.onTextViewChanged(String newName) wherever you want to have the new name in your TextView. Remember to initialize mListener with an instance of your MainActivity first, otherwise you will get a null pointer exception. You can do that either in the constructor of SampleThread or by creating a method for the purpose.

In your activity you should implement SampleThread.TextViewChangeListener and override the onTextViewChanged.

@Override
public void onTextViewChanged(String newName)
{
   //MyTextView.setText(newName);
}

Edit: untested code: MainActivity:

public class MainActivity extends ActionBarActivity implements SampleThread.TextViewChangeListener {
@Override
public void onTextViewChanged(Message msg)
{
    // process incoming messages here
    // i want to change the text of txt1 here
}

public static Handler mHandler;
Runnable thread = new SampleThread(this);
TextView txt1 = (TextView) findViewById(R.id.txt1);
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ActionBar actionBar = getSupportActionBar();
    actionBar.hide();

    //hiding status bar
    if (Build.VERSION.SDK_INT < 16) {
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
    } else {
        View decorView = getWindow().getDecorView();
        int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
        decorView.setSystemUiVisibility(uiOptions);
    }
    setContentView(R.layout.activity_main);
    new Thread(thread).start();
}
}

SampleThread:

package com.example.katsar0v.myapplication;
import android.util.Log; 
/**
* Created by Katsar0v on 1/21/2015.
*/
public class SampleThread implements Runnable 
{
public interface TextViewChangeListener
{
    public void onTextViewChanged(Message msg);
}

public SampleThread(TextViewChangeListener mListener)
{
    this.mListener = mListener;
}

TextViewChangeListener mListener;

@Override
public void run() {
    int two = 0;
    while(two<10) {
        two++;
        try {
            Thread.sleep(1000);
            mListener.onTextViewChanged(String.valueOf(two + "sec"));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
}

Let me know if that helped.