如何在 Android 中通过 Asynctask 返回不同的对象

发布于 2024-11-29 08:31:48 字数 555 浏览 1 评论 0原文

我认为这一定是一个常见问题,但令人惊讶的是我找不到答案,所以也许我的整个结构很糟糕......

我有一个活动通过 AsyncTask 从网络服务下载游戏的值/状态。这些值用于更新自定义视图。

创建视图后,视图中的各种事件都会启动 AsyncTask 来下载其他信息。

这是功能性的,但问题是我现在在活动中有六个 AsyncTask 类,它们的代码几乎相同。唯一的区别是返回的对象类型(基于来自 Web 服务的 json)以及从 onPostExecute() 调用的方法。

在不知道 Web 服务将返回什么类型的 json 对象的情况下,如何仅使用两个 AsyncTask(一个用于 post,一个用于 get)?

同样,如何确定 Web 服务返回的对象类型?如果出现问题,Web 服务将返回与 ErrorMessage 对象相关的 json 字符串,而不是(例如)GameData 对象。

我应该在 onPostExecute() 中使用 switchinstanceof 吗?也许回调?

I figured this must be a common question, but I surprisingly couldn't find an answer, so maybe my entire structure is terribad...

I have an activity which downloads values/states of a game from a web service via AsyncTask. These values are used to update a custom view.

Once the view is created, various events from the view launch an AsyncTask to download other information.

This is functional, but the problem is I now have half a dozen AsyncTask classes in the activity with almost identical code. The only difference is the type of object that is returned (which is based on the json from the web service) and the method that is called from onPostExecute().

How can I use just two AsyncTask (one for post and one for get) without knowing what type of json object will be returned by the web service?

In a similar vein, how can I determine the type of object returned by the web service? The web service, if there is a problem, will return a json string that correlates to an ErrorMessage object rather than (for example) a GameData object.

Should I be using switch and instanceof in onPostExecute() somehow? Callbacks maybe?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不念旧人 2024-12-06 08:31:48

您可以使用抽象基类,您的相关类将扩展该基类。

示例代码:

public abstract class IBaseObject {
    protected String error;

    public IBaseObject(String param) {
        error = param;
    }

    public abstract String getError();
}

public class ObjectOne extends IBaseObject {        
    private String objectParam;        

    public ObjectOne(String error, String objectSpecificParam) {
        super(error);
        objectParam = objectSpecificParam;
    }

    @Override
    public String getError() {
        return error;
    }
}

例如,像这样使用它:

private class GetTask extends AsyncTask<String, Void, IBaseObject> {
    protected IBaseObject doInBackground(String... url) {
        // Get your data.
        // Construct your corresponding object given by specific
        // parameters from your JSON response.
        if (a_parameter_match) {
            return new ObjectOne(some_json_params...);
        } else {
            return new ObjectTwo(some_json_params...);
        }        
    }    

    protected void onPostExecute(IBaseObject object) {
        object.getError(); // Or whatever you need here.
    }
} 

这只是我的想法。我无法理解您的特定问题,尽管这里的想法应该足以让您开始新的结构。

You can use an abstract base class, which your related classes extends.

Sample code:

public abstract class IBaseObject {
    protected String error;

    public IBaseObject(String param) {
        error = param;
    }

    public abstract String getError();
}

public class ObjectOne extends IBaseObject {        
    private String objectParam;        

    public ObjectOne(String error, String objectSpecificParam) {
        super(error);
        objectParam = objectSpecificParam;
    }

    @Override
    public String getError() {
        return error;
    }
}

and for example, use it like this:

private class GetTask extends AsyncTask<String, Void, IBaseObject> {
    protected IBaseObject doInBackground(String... url) {
        // Get your data.
        // Construct your corresponding object given by specific
        // parameters from your JSON response.
        if (a_parameter_match) {
            return new ObjectOne(some_json_params...);
        } else {
            return new ObjectTwo(some_json_params...);
        }        
    }    

    protected void onPostExecute(IBaseObject object) {
        object.getError(); // Or whatever you need here.
    }
} 

This is just from the top of my head. I couldn't relate to your specific problem, although the ideas here should be enough to get you started on your new structure.

哀由 2024-12-06 08:31:48

对于评论来说太长了,所以我正在写一个答案。然而,正是 @Pompe de velo 的建议让我走上了这条道路,所以我接受这个答案。我还从我的问题中遗漏了一些可能有用的信息。

无论如何,到目前为止,我没有看到这种方法有任何重大缺点,但时间(或者也许另一个 SO 用户;])会告诉我们......

本质上,我已经为活动将尝试的每种类型的对象分配了一个常量得到。我遗漏的部分是服务器仅返回 4xx-5xx http 状态代码的错误对象。换句话说,我确定要么得到我期望的对象,要么得到错误对象,并且我可以从状态代码中确定我得到的对象。然后,switch 将实际的 json 字符串发送到可以根据需要操作响应的适当方法。

简化的伪代码...

private void getGameData(){
    new MyAsyncTask(this, MyAsyncTask.OBJ_GAME_DATA).execute();
}

static class MyAsyncTask extends AsyncTask<String, Integer, String> {
    private int outputObjectType;

    protected static final int OBJ_GAME_DATA = 0;
    protected static final int OBJ_OTHER_DATA = 1;
    protected static final int OBJ_DIFFERENT_DATA = 2;
    protected static final int OBJ_SERVER_ERROR = 3;

    MyAsyncTask(MyActivity activity, int expectedObject){
        outputObjectType = expectedObject;
    }

    doInBackground(){
        if(httpStatusCode >= 400){
             outputObjectType = MyAsyncTask.OBJ_SERVER_ERROR;
        }

        return jsonStringFromServer;
    }

    onPostExecute(String json){
        switch(outputObjectType){
        case MyAsyncTask.OBJ_SERVER_ERROR:
            serverError(json);
            break;
        case MyAsyncTask.OBJ_GAME_DATA:
            processGameData(json);
            break;
        // ....
        }
    }
}

private void serverError(String json){
    ServerError se = new Gson().fromJson(json, ServerError.class);
    Log.d(TAG, se.getErrorMessage());
}

private void processGameData(String json){
    GameData gd = new Gson().fromJson(json, GameData.class);
    // .......
}

我认为这更像是 @Pompe de velo 所说的,但是我只是根据状态代码而不是 json 中的内容来制作我的 a_parameter_match

如果这是有缺陷的,我很想知道为什么!

This is too long for a comment, so I'm writing an answer. However it was the advice of @Pompe de velo that got me on this track, so I am accepting that answer. I also left out some information from my question that could have been useful.

Anyway, as of right now I do not see any major downsides to this approach, but time ( or maybe another SO user ;] ) will tell...

Essentially I have assigned a constant to every type of object that the activity will try to get. The part that I left out was that the server only returns an error object on a 4xx-5xx http status code. In other words, I am certain to either get the object I am expecting or an error object and I can determine which I got from the status code. Then a switch sends the actual json string to the appropriate method that can manipulate the response as necessary.

Simplified pseudocode...

private void getGameData(){
    new MyAsyncTask(this, MyAsyncTask.OBJ_GAME_DATA).execute();
}

static class MyAsyncTask extends AsyncTask<String, Integer, String> {
    private int outputObjectType;

    protected static final int OBJ_GAME_DATA = 0;
    protected static final int OBJ_OTHER_DATA = 1;
    protected static final int OBJ_DIFFERENT_DATA = 2;
    protected static final int OBJ_SERVER_ERROR = 3;

    MyAsyncTask(MyActivity activity, int expectedObject){
        outputObjectType = expectedObject;
    }

    doInBackground(){
        if(httpStatusCode >= 400){
             outputObjectType = MyAsyncTask.OBJ_SERVER_ERROR;
        }

        return jsonStringFromServer;
    }

    onPostExecute(String json){
        switch(outputObjectType){
        case MyAsyncTask.OBJ_SERVER_ERROR:
            serverError(json);
            break;
        case MyAsyncTask.OBJ_GAME_DATA:
            processGameData(json);
            break;
        // ....
        }
    }
}

private void serverError(String json){
    ServerError se = new Gson().fromJson(json, ServerError.class);
    Log.d(TAG, se.getErrorMessage());
}

private void processGameData(String json){
    GameData gd = new Gson().fromJson(json, GameData.class);
    // .......
}

I think this is more less what @Pompe de velo was saying, however I am just making my a_parameter_match based on the status code rather than something within the json.

If this is flawed, I'd love to learn why !

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文