如何在旋转之前放置网络呼叫时更新UI线程?

时间:2013-08-09 05:28:06

标签: android handler threadpool

好的,这让我疯了。我有一个工作线程,(网络调用)需要单独运行UI线程,(它实际上是一个ThreadPoolExecutor但我简化它来证明我的观点)。如果以纵向方式运行此代码,而不进行旋转,则文本将更新。我把延迟放在那里以允许轮换显示我的问题。如果以纵向开始,在文本更新旋转到横向之前,文本不会更新。如果您对代码进行注释,则可以看到侦听器触发,但文本永远不会更新。

我正在尝试模拟在单独的线程中运行的自定义网络调用,如果用户在其间旋转然后数据丢失,则可能需要一些时间才能返回。我们正在尝试阻止多个网络呼叫以节省手机上的数据使用情况。

package com.example.test;

import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.content.res.Configuration;
import android.view.Menu;
import android.widget.TextView;
public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    int orientation = getResources().getConfiguration().orientation; 
    if (Configuration.ORIENTATION_LANDSCAPE == orientation) { 
        //Do SomeThing; // Landscape
    } else { 
        startBackgroundWork();
        //Do SomeThing;  // Portrait
    } 

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

private Handler mHandler = new Handler();

public void startBackgroundWork() {
    new WorkingThread(new SomeListener() {
        public void onSomethingDone(final Object result) {

            mHandler.post(new Runnable() {
                public void run() { 
                    ((TextView)findViewById(R.id.text)).setText((String)result);
                    //showMyDialog(result); 
                }
            });

        }    
    }).start();
}

public interface SomeListener {
    public void onSomethingDone(Object result);
}

public class WorkingThread extends Thread {
    private SomeListener mListener;

    public WorkingThread(SomeListener listener) {
        mListener = listener;
    }

    public void run() {
        /* do some work */
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        mListener.onSomethingDone("New Text");
    }
}
}

1 个答案:

答案 0 :(得分:1)

这是因为在轮换时,会重新创建活动,因此您的所有代码都绑定到旧活动。你应该引用你的工作线程:

private static WorkingThread mWorkingThread;
public void startBackgroundWork() {
    mWorkingThread = new WorkingThread(new SomeListener() {
        public void onSomethingDone(final Object result) {

            mHandler.post(new Runnable() {
                public void run() { 
                    ((TextView)findViewById(R.id.text)).setText((String)result);
                    //showMyDialog(result); 
                }
            });

        }    
    }).start();
}

然后onCreate更新它:

public class WorkingThread extends Thread {
    private SomeListener mListener;

    public WorkingThread(SomeListener listener) {
        mListener = listener;
    }

    public void run() {
        /* do some work */
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        mListener.onSomethingDone("New Text");
    }

    public void updateListener(SomeListener listener) {
        mListener = listener;
    }
}


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    startBackgroundWork();
}

public void startBackgroundWork() {
    if (mWorkingThread == null || mWorkingThread.isFinished()) { // Use a boolean to know if it still running


    mWorkingThread  = new WorkingThread(new SomeListener() {
        public void onSomethingDone(final Object result) {

            mHandler.post(new Runnable() {
                public void run() { 
                    ((TextView)findViewById(R.id.text)).setText((String)result);
                    //showMyDialog(result); 
                }
            });

        }    
    });
        mWorkingThread.start();

    } else { 
        mWorkingThread.updateListener(new SomeListener() {
        public void onSomethingDone(final Object result) {

            mHandler.post(new Runnable() {
                public void run() { 
                    ((TextView)findViewById(R.id.text)).setText((String)result);
                    //showMyDialog(result); 
                }
            });

        }    
    });
    } 
}

但是你可以做一些改进:

  • WorkingThread类应该是静态的,以避免直接引用旧活动:Java: Static vs non static inner class

  • 然后引用当前活动,并在重新创建时更新

  • 制作更新文本的方法,而不是将代码直接放在侦听器中