簡體   English   中英

Android主線程與其他線程之間的通信

[英]Android communication between main thread and other thread

我想動態更改textview的文本,但是如果要創建游戲線程,我將需要相同的邏輯,因此需要在主線程和第二線程之間進行通信。

我有文件:

主要活動

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

我看到的問題是,當我的線程位於另一個文件中時,如何使用處理程序更改文本? 還是應該讓第二個類在第一個類中保持靜態(當代碼過長而又不能全部放在一個文件中時該怎么辦)?

您可以實現一個自定義Interface ,以便從您的主要活動中對其進行處理。 在您的SampleThread

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

然后,只要您想在TextView擁有新名稱,就調用mListener.onTextViewChanged(String newName) 請記住, mListener使用MainActivity的實例初始化mListener ,否則將獲得空指針異常。 您可以在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();
        }
    }
}
}

讓我知道是否有幫助。

您可以在Grafika中找到一些示例,該示例在UI線程上做了很多工作。 例如, TextureFromCameraActivity有一對處理程序,一個用於UI線程,一個用於渲染器線程。 onResume()您可以看到主線程通過構造函數將其處理程序傳遞給渲染器,然后通過方法調用檢索渲染器線程的處理程序。

ContinuousCaptureActivity使用的處理程序稍有不同,該處理程序還實現了回調接口。 該處理程序對象作為接口實例傳遞給CircularEncoder構造函數。 公共回調方法在內部使用Handler。

唯一棘手的問題是,如果要從非UI線程傳遞處理程序。 您要么需要在線程啟動之前執行此操作,要么使用適當的線程同步操作來避免數據爭用

您無需將類放在同一個文件中(除非一個嵌套在另一個文件中,否則您實際上不應該這樣做)。 如果它們在同一個程序包中,則默認(程序包)范圍將使他們能夠相互看到。 Grafika的第一個示例使用了嵌套/私有類,第二個示例則更加分散。

當然,如果您要做的只是從非UI線程提交UI事件,則可以只使用Activity.runOnUiThread()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM