主线程与其他线程之间的Android通信

时间:2015-01-21 17:05:23

标签: java android

我想动态更改textview的文本,但如果我想制作一个游戏线程,我需要相同的逻辑,所以我需要在主要的和第二个之间进行通信。

我有文件:

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();
            }
        }
    }
}

我看到的问题是,当我的线程在另一个文件中时,如何使用处理程序更改文本?或者我应该在第一个类中使第二个类静态(当代码变得非常长时,我应该怎么做,它不能都在一个文件中)?

2 个答案:

答案 0 :(得分:0)

您可以实施自定义Interface,以便从主要活动中处理它。 在SampleThread上:

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

然后在mListener.onTextViewChanged(String newName)中的任何地方拨打TextView。请记住首先使用mListener的实例初始化MainActivity,否则您将获得空指针异常。您可以在SampleThread的构造函数中执行此操作,也可以为此创建方法。

在您的活动中,您应该SampleThread.TextViewChangeListeneroverride onTextViewChanged

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

修改:未经测试的代码: 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();
        }
    }
}
}

如果有帮助,请告诉我。

答案 1 :(得分:0)

您可以在Grafika中找到一些示例,它们可以在UI线程中完成大量工作。例如,TextureFromCameraActivity有一对处理程序,一个用于UI线程,一个用于呈现器线程。在onResume()中,您可以看到主线程通过构造函数将其处理程序传递给渲染器,然后通过方法调用检索渲染器线程的处理程序。

ContinuousCaptureActivity有一个稍微不同的方法,使用也实现回调接口的Handler。处理程序对象作为接口实例传递给CircularEncoder构造函数。公共回调方法在内部使用Handler。

唯一棘手的问题是,如果您将Handler传递出非UI线程。您需要在线程启动之前执行此操作,或使用适当的线程同步操作来避免data races

您不需要将您的课程放在同一个文件中(除非有人嵌套在另一个文件中,否则您真的不应该这样做)。如果他们在同一个包中,那么默认(包)范围将让他们看到对方。 Grafika的第一个例子使用嵌套/私有类,第二个例子更加分散。

当然,如果你要做的只是从非UI线程提交UI事件,你可以使用Activity.runOnUiThread()