0

请参考以下代码,该代码从 PHP 脚本中获取一些信息,并将其显示在我的手机上:

package room.temperature;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

public class RoomTemperatureActivity extends Activity {

    String result = null;
    StringBuilder sb=null;

    TextView TemperatureText, DateText;
    ArrayList<NameValuePair> nameValuePairs;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        TemperatureText = (TextView) findViewById(R.id.temperature); 
        DateText = (TextView) findViewById(R.id.date); 
        nameValuePairs = new ArrayList<NameValuePair>();
    }

    @Override
    public void onResume() {
        super.onResume();
        //setValues();

        for (int i = 0; i < 10; i++) {
            setValues();
        }
    }

    public void setValues() {

        InputStream is = null;

        try {
            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost("http://mywebsite.com/tempscript.php");
            httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
            HttpResponse response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();
            is = entity.getContent();
        }

        catch(Exception e)  {
            Log.e("log_tag", "Error in http connection" + e.toString());
        }

        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
            sb = new StringBuilder();
            sb.append(reader.readLine());
            is.close();
            result=sb.toString();
        }

        catch(Exception e)  {
            Log.e("log_tag", "Error converting result " + e.toString());
        }

        System.out.println(result);

        String[] values = result.split("&");

        TemperatureText.setText(values[0]);
        DateText.setText(values[1]);

    }
}

当我注释掉 for 循环并且只调用setValues()一次时,这段代码效果很好。但是,一旦我引入循环,main.xml(或屏幕上的任何内容)在循环完成之前不会加载。我认为它与活动生命周期有关,但无论我尝试将代码放在哪里,它都无法正常工作。本质上,我希望这些值在我每次调用时都保持更新setValues()。10 次迭代循环仅用于测试概念。

4

2 回答 2

4

您需要了解 UI 线程是如何工作的,以了解为什么在循环完成之前您什么都看不到。UI 线程包含一个消息循环,其中消息(您可以将它们视为小代码块)被推送到其中并串行执行(一次 1 个)。当 UI 线程运行您的代码时,它将执行您要求的所有操作,但屏幕上的值将被“发布”,或发送到消息循环中,以便在下一个可用时间实际放置在屏幕上。你不应该在 UI 线程上做长时间运行的操作,这就是为什么 Android 系统提出了多种处理长时间运行的操作的方法。最常见的场景是使用 AsyncTask。

Http 调用永远不应该在 UI 线程上执行,事实上这将在运行蜂窝或更高版本的设备上失败(除非您在代码中引入一些 hack)。

您应该将 http 调用放在方法中的AsyncTaskdoInBackground。然后设置onPostExecute可以调用 UI 方法的方法(.setText 方法)。您需要将所有数据放入某种数据结构中,例如 doInBackground 方法中的 ArrayList。

于 2012-10-26T03:35:57.153 回答
0

非常有趣的问题,根据我的一位前辈的说法,当您提出更改或重绘 UI 的请求时,会调用 GPU 进行更改所以当第一行执行进行更改时,会通知 GPU 并进行更改并且控制现在回到下一行,在你的情况下它是一个循环,所以它基本上等待循环完成(循环内循环)然后重绘或重绘它

因此,如果您这样做,我建议您不要将其置于循环中

setValues(); // 1st Time
setValues(); // 2nd Time
setValues(); // 3rd Time
setValues(); // 4th Time
setValues(); // 5th Time
setValues(); // 6th Time
setValues(); // 7th Time
setValues(); // 8th Time
setValues(); // 9th Time
setValues(); // 10th Time

并查看是否在每次通话中都进行了更改(我知道这不是您的解决方案,但这只是为了理解目的)

如果我要提出一个解决方案,那么我会说使用异步任务来更新 UI,因为在 3.0 蜂窝之后,无法从主线程对 UI 进行任何更改

有关异步任务,请参阅此http://www.vogella.com/articles/AndroidPerformance/article.html

于 2012-10-26T05:54:26.310 回答