0

我有一个线程需要一直从网络接收数据,我希望将这些数据显示到 EditText 对象。

显然,我无法从接收线程中访问 UI EditText;我读到的是我可以使用 AsyncTask 但阅读Painless Threading中的示例在我看来,我必须先完成接收数据,然后才能将结果发布到 UI 组件。

我不能使用 post 或 postDelayed 因为两者都将在 UI 线程上运行,并且我不能阻止 UI 接收数据;我需要一直接收数据。

我还有什么其他选择?

4

4 回答 4

1

使用 LocalBroadcastManager,包含 TextView 的 Activity 将开始监听广播:

public class MyActivity extends Activity {

    private TextView mTextView;
    BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getStringExtra("actionType");
            if(action.equals("updateTextView")){
                mTextView.setText("whatever you want to set");
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //Start listening, you can put it on onResume too
        LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, new IntentFilter(MyActivity.class.getSimpleName()));
        mTextView = (TextView) findViewById(R.id.something);
    }
}

因此,每当您的线程收到需要更新屏幕的内容时,请调用:

Intent intent = new Intent(MyActivity.class.getSimpleName());
intent.putExtra("actionType", "updateTextView");

// Once this is called, your broadcast receiver in MyActivity should receive it and start processing
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);

还记得在 onDestroy 或 onPause 中取消注册它。

*旁注:您需要导入android支持v4库,您可以使用 Intent.putExtra("","") 和 Inteng.getExtra("");

于 2013-05-07T01:59:30.760 回答
0

另一种方法是实现数据监听器接口。

public interface DataListener{
    void onUpdateData(MyData data);
}

包含需要更新的 UI 组件的活动将实现此接口。它将指定如何处理更新的数据。您可能希望将这些数据侦听器接口的所有实例保留在应用程序的某个位置。我假设您有一个不同的线程来处理网络发送/接收操作。在接收数据时,您只需调用:

dataListenerInstance.onUpdateData(data)

然后它将激活您在活动中实现的处理程序。

于 2013-05-07T02:06:04.597 回答
0

在 MainActivity 调用 AsyncTask 但将 @Override 方法设为 onPostExecute(..)

    public class MainActivity extends ActionBarActivity{
    ...
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if(Utils.isNetworkAvailable(this)) {
          DownloadFileFromURL downloader = new DownloadFileFromURL(){
               @Override
               protected void onPostExecute(Integer file_content) {
                                    onCompleteLoad();
                                }
                            };
               downloader.execute(new String[]{file_url, fileName});

               ...

onCompleteLoad(); - 将在 MainActivity 的 UI 线程中调用。你甚至不需要实现接口!

第二种方式更适合服务端解决方案,但也可以用在客户端它是Callable

public class DoGetSize implements Callable<Integer> {
    private final String file_url;
    private int lenghtOfFile = -1;

    public DoGetSize(String file_url) {
        this.file_url = file_url;
    }

    public Integer call() {
        try {
            URL url = new URL(file_url);
            URLConnection connection = url.openConnection();
            connection.connect();
            lenghtOfFile = connection.getContentLength();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return lenghtOfFile;
    }
}

并称其为:

    FutureTask<Integer> task = new FutureTask(new DoGetSize(file_url));
    ExecutorService es = Executors.newSingleThreadExecutor();
    es.submit (task);
    try {
        Integer result = task.get();
        File file = new File(fileName);
        if(file.length() != result.intValue()) {
          // Do something
           ...
        }

    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    }

您可以通过这种方式发送和接收任何对象

完整示例见 github:https ://github.com/app-z/OffLineShop/blob/master/app/src/main/java/net/appz/offlineshop/offlineshop/MainActivity.java

于 2015-02-14T22:02:03.990 回答
-1

您可以使用简单的委托来执行此操作。

class NonUIThread { 
     private NonUIThreadDelegate delegate; //NonUIThreadDelegate can be an interface or an object that has access to your UI thread like an Activity

     public void setDelegate(NonUIThreadDelegate delegate) {
        this.delegate = delegate;
     }

     private void doSomthing() { 
        //do something and at the end:
        delegate.someMethodThatUpdatesThatComponent();
     } 
 }

class TheUIThread implements NonUIThreadDelegate /*assuming you've decided to make NonUIThreadDelegate an interface*/ { // the "delegator"
    /*
    your code
    */

    private void initiateNonUIThread() {
        NonUIThread nonUIThread;
        /*do whatever needed*/
        nonUIThread.setDelegate(this);
        nonUIThread.start();
    }

    public void someMethodThatUpdatesThatComponent() { //will be called by the non ui thread
        //update the UI
    }   
 }

在这里解释得更好(当然使用 AsincTask):Android 中的简单委托模式

于 2013-05-07T02:06:00.453 回答