kir*_*off 1 java multithreading android httpclient android-asynctask
我正在尝试创建简单的Android程序,每30*1000毫秒拉一次Web服务器.我在我的应用程序中有专门的服务 - PollerService
Android Manifest.xml:
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".PullServerAndListenActivivty"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".PollerService" />
</application>
Run Code Online (Sandbox Code Playgroud)
该类创建计划执行程序并注册其计时器任务以开始调用Engine,以便拉出服务器.
PollerService.java:
public class PollerService extends Service {
public static final int INTERVAL = 20*1000;
private ScheduledExecutorService executor;
public void onCreate() {
super.onCreate();
executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(new TimerTask() {
public void run() {
Engine.tick ();
}
}, 0, INTERVAL, TimeUnit.MILLISECONDS);
}
public void onDestroy() {
executor.shutdownNow();
}
public IBinder onBind(Intent arg0) {
return null;
};
}
Run Code Online (Sandbox Code Playgroud)
Engine只在GUI线程中创建AsyncTask子类实例并执行它.onPostExecute通过在Activity中分配的控制台写入一行,并调用UI组件.
public class Engine {
private static Console console; //Assigned in Activity onCreate
private static Activity context;//Assigned in Activity onCreate
...
public static void tick() {
final String requestURL = String.format(urlFormat, serverURL);
try {
context.runOnUiThread(
new Runnable () {
public void run() {
new RequestTask().execute(requestURL);
};
}
);
}
catch (Throwable e) {
Log.e("SBOX", e.getMessage(), e);
}
}
public static void processCommand(String result) {
try {
final Command command = fromJSONToCommand(result);
context.runOnUiThread(new Runnable() {
public void run() {
console.writeLine("Receieved command: " + command);
}
});
} catch (Exception e) {
Log.e ("SBOX", e.getMessage(), e);
}
}
Run Code Online (Sandbox Code Playgroud)
牦牛,我从简单的RequestTask实例创建开始,我的印象是它将自己在UI线程上运行,但试图解决问题我终于来到这种方法,仍然没用.只是想说我在这里尝试了很多.
RequestTask看起来像这样,简单的http调用:
class RequestTask extends AsyncTask<String, Void, String>{
@Override
protected String doInBackground(String... uri) {
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response;
String responseString = null;
try {
response = httpclient.execute(new HttpGet(uri[0]));
StatusLine statusLine = response.getStatusLine();
if(statusLine.getStatusCode() == HttpStatus.SC_OK){
ByteArrayOutputStream out = new ByteArrayOutputStream();
response.getEntity().writeTo(out);
out.close();
responseString = out.toString();
} else{
response.getEntity().getContent().close();
throw new IOException(statusLine.getReasonPhrase());
}
} catch (Exception e) {
Log.e("SBOX", e.getMessage(), e);
}
return responseString;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Engine.processCommand (result);
}
}
Run Code Online (Sandbox Code Playgroud)
所以问题是它只运行一次,定时器调度,第一次调用Engine,它运行RequestTask,它拉动服务器,获取响应,在控制台中打印它.但第二次它进入计时器方法,然后从服务没有生命迹象.LogCat中没有例外,不打印登录RequestTask.
当然是时候调试了,但可能有人可以免除这种痛苦并在代码中显示错误?如果要对Engine.tick()调用进行注释,则执行程序本身可以完全连续工作.
对解决问题的线索非常感兴趣.
我正在尝试创建简单的Android程序,每30*1000毫秒拉一次Web服务器.
你肯定会以艰难的方式去做.
步骤1:在您的活动和服务之间建立真实的沟通渠道.不要使用静态数据成员,因为您正在创建可能的内存泄漏.有很多考生(createPendingResult(),Messenger,等).为了这个答案,我将假设您将使用广播Intent,因此选择一些独特的动作字符串并在您的活动中设置一个BroadcastReceiverin onResume()来监听这样的广播(并删除该接收者onPause()).
第2步:pollServer()在您的服务中创建一个方法,该方法包含来自您的doInBackground()方法的代码RequestTask.但是,不是返回一个字符串,而是让它发送广播Intent,并将你的字符串作为额外的.
第3步:pollServer()来自你的呼叫ScheduledExecutorService,而不是Engine.tick().
第四步:删除Engine并RequestTask完全删除.
| 归档时间: |
|
| 查看次数: |
2342 次 |
| 最近记录: |