0

问题是如何通过Android手机与服务器进行通信,以便在离开Activity并且Activity中的调用不成功时自动再次重复事务。刚才我使用Android的AsyncTask与服务器通信:

new AsyncTask<String, Void, List<String>>() {

    @Override
    protected void onPreExecute(
       showWaitDialog();        
    }

    @Override
    protected void onPostExecute(List<String> msgList) {
       //here I put the handling after the POST ie. error and success handling
       hideWaitDialog();

       if (msgList.isEmpty() {
          //success handling --> starting an new Activity
       } else {
          errorView.setText (...);
          errorLayout.setVisibility (View.VISIBLE); 
       }
    } 

    @Override
    protected List<String> doInBackground(String... params) {
       List<String> msgs = new ArrayList<String>();
       try{
          //for example submitting an JSONObject
          JSONObject result = HttpUtils.sendHttpPost(
              AppConstants.WEB_URL, jsonObject);
          //error handling on the result
          boolean hasErrors = JsonResult.isOk(result);
          if (hasErrors) {
              // adding errors to msgs list
              String[] errorMessages = JsonResult.getErrorMessages (result,...);           
              fillList (msgs, errorMessages);
              return msgs;
          }
       } catch (CommunicationError er) {
           msgs.add (er...);
       }
       return msgs;
    }
 } 

这种方法的问题是,如果我没有成功传输数据,我必须留在同一个 Activity 中。到目前为止,我向用户显示了一条错误消息,他负责通过按钮再次将结果提交给服务器。我正在寻找的是一些在内存中保持持久性的 Activity,它会在未进行传输的情况下稍后运行。

作为一个应用案例,如果我按下该航点,我会使用它来动态上传地图中航点的图片。在某些情况下,移动服务提供商的连接可能不可用(山脉、森林、远离天线)。然后我想离开地图Activity,切换到这个航点的详细视图。在成功案例中,我将图片放入我的模型类并进行序列化。如果用户再次单击同一航点,则不会再次加载图片。在不成功的情况下,我不想等待用户点击航路点来检索图像。事实上,我需要一个后台任务,某种队列,已经访问过的航路点的图片不能' 检索到的 t 被加载,直到通信部分返回一个肯定的结果并且图像可以写入模型中。下一次用户按下 Waypoint 时,图片就会出现。

是否有进行此类代码实现的最佳实践?周围有例子吗?有没有更好的方法来做到这一点?

4

2 回答 2

0

是的,您需要Intent Service为此要求实施

根据开发者网站

IntentService 类为在单个后台线程上运行操作提供了一个简单的结构。

有关完整的详细信息和工作源代码,请浏览Android Docs

于 2014-05-30T08:47:48.220 回答
0

感谢大卫的回答。

我刚刚在建议后阅读了教程

[1] http://code.tutsplus.com/tutorials/android-fundamentals-intentservice-basics--mobile-6183

经过我的测试,我更喜欢服务(不是 IntentService)

并创建了一个服务:SubmissionService

public class SubmissionIntentService extends Service {

    private List<PendingMessage> pMsgList = new CopyOnWriteArrayList<PendingMessage>();
    private Handler handler = new Handler();
    private boolean hasAppStopped = false;
    private Runnable runner;


    public SubmissionIntentService() {
      super();
      Log.d (TAG, "Service created...");
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
      PendingMessage pMessage = (PendingMessage) intent.getParcelableExtra(AppConstants.MESSAGE_OBJECT);
      synchronized (pMsgList) {
         pMsgList.add(pMessage);
      }
      if (runner == null) {
         handler.postDelayed(runner = initializeRunnable(), 500);
      }
      return Service.START_NOT_STICKY;
   }

    private void runAsLongAppIsActive (Runnable runner) {
        if (!hasAppStopped) {
           handler.postDelayed (runner, SOME_INTERVAL_CONSTANT); 
        }
    }

    private Runnable initializeRunnable() {
        Runnable result;
        result = new Runnable() {

             @Override
             public void run() {
                if (pMsgList.isEmpty()) {
                   runAsLongAppIsActive (this);
                   return; 
                }

                PendingMessage[] pMArray = null;

                synchronized(pMsgList) {
                    pMArray = pMsgList.toArray (new PendingMessage[pMsgList.size()]);
                } 
                if (pMArray==null || pMArray.length==0) {
                   runAsLongAppIsActive (this);
                   return;
                }
                Log.d (TAG, "Message List size is actually :"+pMArray.length);

                for (PendingMessage pM: pMArray) {
                     try {
                        JSONObject jsonMess = JSONSendMessage.buildOutput (pM);
                        JSONObject result = HttupUtils.sendHttpPost (WEB_URL, jsonMess);

                        boolean hasErrors = JSONResult.isOk (result);
                        if (hasErrors) {
                           //TODO: error handling in case of transmission
                           //don't remove the message from the queue
                           runAsLongAppIsActive(this); 
                           return; 
                        }
                        //remove pending transmission of the queue if success
                        synchronized (pMsgList) {
                           pMsgList.remove (pM);
                        } 
                        //inform over receiver if activity is shown
                        Intent broadcastIntent = new Intent();
                        //put data in intent
                        sendBroadcast (intent);

                        //more important
                        WayPointModel model = ModelInstance.getWayPointModel();
                        model.addToModel (pM, result);
                        model.store();

                     } catch (Exception e) {
                        continue; //try to send other messages
                     }
                }
                runAsLongAppIsActive (this);
             }

           };
        return result;
    }
}

   @Override
   public void onDestroy() {
      hasAppStopped = true;
      handler.removeCallbacks (runner);
      super.onDestroy();
   }

}

此外,我添加了一个 ResponseReceiver:

public class ResponseReceiver extends BroadcastReceiver {
   public static final String ACTION_RESP = "MESSAGE_PROCESSED";

   @Override
   public void onReceive(Context context, Intent intent) {
      //work in progress...
   }
}

在我想了解事件的活动中:

public class SomeActivity extends Activity {    
  private ResponseReceiver receiver;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    IntentFilter filter = new IntentFilter(ResponseReceiver.ACTION_RESP);
    filter.addCategory(Intent.CATEGORY_DEFAULT);
    receiver = new ResponseReceiver();
    registerReceiver(receiver, filter);
    ...
 }

}

最后通过 Http 发送消息:

Intent msgIntent = new Intent(this, SubmissionIntentService.class);
msgIntent.putExtra(...);
startService(msgIntent);

不要忘记在清单中声明服务:

<service android:name="ch.xxx.app.service.SubmissionIntentService" />

观察: - 我从不同的活动中调用了方法 startService(...)。构造函数只被调用一次。==>我刚刚为所有活动提供了服务实例(正是我需要的)。

直到现在我还没有得到: - 将数据放回活动。如果 Activity 目前没有显示怎么办?

于 2014-05-30T12:15:29.947 回答