Far*_*mor 1 java oop android asynchronous http
我决定学习Scala/Play(服务器端),并决定同时学习Android(客户端)游戏开发以增加开发.
我有一个关于如何在Android中为HTTP请求设计好的问题.
根据我的理解,最好的方法是将HTTP请求委托给扩展抽象AsyncTask类的类.
您是否必须为您覆盖AsyncTask的doInBackground方法中的每个不同逻辑执行新的扩展?
对我来说,为每个请求逻辑创建一个类并不是很自然,而是在一个类中封装了几个连贯的方法.
我刚刚开始玩一点,但我对设计不满意,因为我不喜欢我设计的varargs对象doInBackground(Object... params).
通过这种设计,我放松了类型安全性,并且params对象远非直观和直观,这是我在代码中努力的方法.
这是我想要改进的代码.
public class GameActivity extends Activity {
private class MyCellListener implements ICellListener {
public void onCellSelected() {
ServerProxy.postSelectedCell(row, col, player.getUser());
...
// ServerProxy.other();
public class ServerProxy extends AsyncTask<Object, Void, Void>{
private static final String TAG = ServerProxy.class.getSimpleName();
private static final String SERVER_ADDRESS = "http://127.0.0.1";
// Prevent external instantiation
private ServerProxy(){};
public static void postSelectedCell(int row, int cell, User user){
List<NameValuePair> postParameters = new ArrayList<NameValuePair>(3);
postParameters.add(new BasicNameValuePair("row", String.valueOf(row)));
postParameters.add(new BasicNameValuePair("cell", String.valueOf(cell)));
postParameters.add(new BasicNameValuePair("userName", user.getUserName()));
new ServerProxy().doInBackground("setSelectedCell" , postParameters);
}
// public static void postOther() {
// new ServerProxy().doInBackground("other" , //some parameters);
// }
/**
* @param postParameters First object URL postfix<br/>
* Second parameter is post parameters inform of {@code List<NameValuePair>}
* @return null
*/
@SuppressWarnings("unchecked")
@Override
protected Void doInBackground(Object... params) {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(SERVER_ADDRESS +"/" + params[0]);
httppost.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, false);
try {
httppost.setEntity(new UrlEncodedFormEntity((List<NameValuePair>) params[1]));
httpclient.execute(httppost);
} catch (ClientProtocolException e) {
Log.e(TAG,e.toString());
} catch (IOException e) {
Log.e(TAG,e.toString());
}
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
我想你不明白AsyncTask的作用.你无法在单个AsyncTask子类上定义postLastName,postFirstName,postWhatever等方法,并让它从UI线程执行该方法调用.AsyncTask旨在使您更容易执行需要更新UI的后台作业,而不必强制您直接处理线程.
为了与您正在使用HttpClient的服务器通信,调用HttpClient.execute()将阻塞,直到服务器的响应返回.这可能需要很长时间,特别是如果服务器繁忙,死机或电池无线电发生故障.当该调用时间过长时,您不希望UI停止响应用户.你想展示一个旋转器,让用户知道发生了什么.如果您使用了您提供的代码,那么您将在返回的HttpClient.execute()调用之前使用您的UI来进行绘制,因为您在UI线程上调用它.
解决这个问题的方法是将这个调用从UI线程移到另一个线程上.让该线程等待响应,然后让它通知UI线程完成它并使用UI线程用新数据更新UI.为什么不能让后台线程更新UI?因为这会违反Android的线程规则,该规则只表示UI线程可以更新UI.
AsyncTask允许您运行UI线程(doInBackground()),并将返回值发布到UI线程(onPostExecute()),以便它可以安全地更新UI而不违反Android的规则.你不直接调用doInBackground()或onPostExecute(),而是调用AsyncTask.execute(),AsyncTask中的代码将在后台线程上调用doInBackground(),当它完成时,它将在UI线程上调用onPostExecute() .这样你就不会因为自己做所有的线程而纠缠不清.
现在,您通过单个子类运行多个请求的想法不会起作用,因为AsyncTask将服务调用的两个部分联系在一起:执行服务调用以获取响应的详细信息,以及如何处理更新响应用户界面.如果调用postFastName()方法,则在返回该响应之后执行的操作可能与调用postLastName()有所不同.而且因为它的不同意味着你不能只为所有这些不同的调用定义一个AsyncTask.您可以通过组合或子类化基类来共享代码,但是您必须为要在服务器上执行的每个唯一操作创建子类.因此,对于每个调用,请考虑Class而不是Method.
您不必使用传递给doInBackground()的参数.如果您有多种类型的参数传递给AsyncTask.在构造函数中传递它们.因为您无法重用AsyncTask实例(即每个实例不能多次调用AsyncTask.execute()).他们的生命周期必须是实例化,执行()和折腾.这意味着在构造函数中传递输入不会损害您使用AsyncTask的能力.
我编写了自己的AsyncTask版本,它分离出三个回调方法:success(),用于处理从doInBackground()返回的结果; 当从doInBackground()抛出任何异常时调用handleException(); 和doFinally()调用,无论doInBackground()返回什么或引发异常.默认情况下,无论错误或成功如何,都会调用asyncTask onPostExecute().它看起来像这样:
public class MyTask extends EnhancedAsyncTask<Param,Integer,MyResult> {
MyParam1 param1;
MyParam2 param2;
public MyTask( MyParam1 param1, MyParam2 param2 ) {
this.param1 = param;
this.param2 = param2;
}
protected MyResult doInBackground( Param... params ) {
// do server work here
server.send( param1, param2 );
}
protected void success( MyResult result ) {
// do Update of the UI
}
protected void handleException( Exception ex ) {
// show an error here
}
}
// Now to use this AsyncTask you would do something like this:
MyTask task = new MyTask( param1, param2 ).execute();
Run Code Online (Sandbox Code Playgroud)
通常我会将其作为匿名内部类来执行,因此不需要传递对UI的引用,但是如果不执行Anon类,则可以将它们传递给构造函数.如果活动被销毁(例如用户翻转屏幕),您必须小心不要触摸UI.
| 归档时间: |
|
| 查看次数: |
1770 次 |
| 最近记录: |