【问题标题】:Thread in fragment with setRetainInstance(true)带有 setRetainInstance(true) 的片段中的线程
【发布时间】:2016-09-09 15:46:21
【问题描述】:

我有一个片段,里面有一个线程,从它的 onCreate 方法开始。

线程完成他的工作后,我需要通过“clickButtonOperation”向活动(myActivity)发送消息。

这是我的片段的 onCreate() 方法:

public class HolderFragment extends My_Fragment{

private Thread myThread;

.
.
.

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setRetainInstance(true);
    printf("MyActivity attached is: "+myActivity);

    myThread=new Thread(new Runnable(){


        @Override
        public void run() {

            int i=0;
            while (i<3){

                printf("Working...");
                try {

                    Thread.sleep(2000);
                }
                catch (InterruptedException e) {

                    e.printStackTrace();
                }
                i++;
            }

            myActivity.clickButtonOperation(new Object[]{

                    HolderFragment.this.toString()
            });
        }
    });

    myThread.start();
}

onCreateView 返回 NULL。

我的问题是: 是否保证在附加新活动后调用我的“clickButonOperation”?还是可以在这个过程之前调用这个方法?

临时解决方案:

我创建了一个自定义线程类:

public abstract class My_Thread extends Thread {

private boolean runnable=true;
private boolean paused=false;
private Object[] arguments;
private My_ThreadHolder myHolder;

protected void onPostExecute(Object[] arguments){

    while(paused);
    runnable=false;
}

protected abstract void execute(Object[] arguments);

protected void notifyUpdate(){

    while (paused);
}

protected boolean isRunnable(){

    return runnable;
}

public void setArguments(Object[] arguments){

    this.arguments=arguments;
}

public Object[] getArguments() {

    return arguments;
}

public final void run(){

    while (runnable){

        execute(arguments);
        onPostExecute(arguments);
    }
}

public void attach(My_ThreadHolder holder){

    myHolder=holder;
}


public My_ThreadHolder getHolder() {

    return myHolder;
}

public void startThread(){

    runnable=true;
    start();
}

public void stopThread(){

    runnable=false;
}

public void pauseThread(){

    paused=true;
    printf("Thread paused");
}

public void resumeThread(){

    paused=false;
    printf("Thread resumed");
}
}

并创建了这两个:

public class My_ThreadHolder extends My_Fragment{

private TestThread myThread;

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setRetainInstance(true);
    printf("MyActivity attached is: "+myActivity);
    myThread=new TestThread();
    myThread.attach(this);
    myThread.startThread();
}

@Override
public void onAttach(Context context) {
    super.onAttach(context);

    if (myThread!=null)myThread.resumeThread();
}

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

    myThread.pauseThread();
}

protected void onNotifyUpdateReceived(Object[] arguments){

    myActivity.clickButtonOperation(arguments);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {return null;}

@Override
protected void setGraphics(View view, Bundle savedInstanceState) {}
}

class TestThread extends My_Thread{


@Override
protected void onPostExecute(Object[] arguments) {
    super.onPostExecute(arguments);

    printf("Thread finished");
}

@Override
protected void execute(Object[] arguments) {

    int i=0;
    while(i<3){

        printf("Working...");

        try {

            Thread.sleep(2000);
        }
        catch (InterruptedException e) {

            e.printStackTrace();
        }
        i++;

        Object[] myArguments= new Object[2];
        myArguments[0]=0;
        myArguments[1]=i;
        setArguments(myArguments);
        notifyUpdate();
    }
}

@Override
protected void notifyUpdate() {

    super.notifyUpdate();

    getHolder().onNotifyUpdateReceived(getArguments());
}
}

【问题讨论】:

    标签: android multithreading user-interface fragment


    【解决方案1】:

    您不能从后台线程触摸 UI。您需要使用 Activity 类中的 runOnUiThread 方法,类似这样

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        setRetainInstance(true);
        printf("MyActivity attached is: "+myActivity);
    
        myThread = new Thread(new Runnable() {
            @Override
            public void run() {
                int i = 0;
                while (i < 3) {
                    printf("Working...");
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    i++;
                }
    
                myActivity.runOnUiThread(new Runnable() {
                     @Override
                     public void run() {
                         myActivity.clickButtonOperation(new Object[]{
                             HolderFragment.this.toString()
                         });
                     }
                });
            }
        });
    
        myThread.start();
    }
    

    【讨论】:

    • 我喜欢你的解决方案,顺便说一下,我的意图不是触摸 ui,而是简单地通知 mainactivity 做某事。我应该始终使用这种方法吗?
    • 上面带有 setRetainInstance(true) 的代码会造成内存泄漏问题。您需要正确处理 mActivity。你只能使用线程?
    • 是的,我将使用 AsyncTask 进行检查,但现在我必须使用线程...你能建议任何聪明的方法来处理它而不发疯吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-24
    • 2013-04-24
    • 1970-01-01
    • 2014-07-07
    • 2013-08-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多