简体   繁体   English

从doInBackground将泛型用于不同的返回类型的异步任务

[英]Async task using generics for different return types from doInBackground

I have a utility class that extends Async task. 我有一个扩展异步任务的实用程序类。 I will be using this call to make HTTP requests in the background but I will also have more specialized sub classes of this that prepare the parameters, headers, url to call, so I can remove more common work from the GUI. 我将使用此调用在后台发出HTTP请求,但我还将拥有更专门的子类来准备要调用的参数,标头和url,因此可以从GUI中删除更常见的工作。

The issue is that I want to make use of Generics. 问题是我想使用泛型。 The base API class doInBackground will return a string, there's a more specialized Json subclass that will call parent and return a JSONObject and do some parsing of the json response, there's specialized classes that extend the Json subclass and return List of custom objects, and so on. 基础API类doInBackground将返回一个字符串,还有一个更专门的Json子类,它将调用parent并返回一个JSONObject并进行json响应的解析,还有一些专门的类扩展了Json子类并返回自定义对象的列表,等等。上。 The reason for this is if we need to swap in XML and XML processing the specialized sub classes will have both a JSON and XML implementation. 原因是如果我们需要交换XML和XML处理功能,那么专门的子类将同时具有JSON和XML实现。 This is because we are re-using for a couple different api's overall. 这是因为我们正在整体使用几个不同的api。

So I tried playing around with Generics but I'm not 100% sure I understand the implementation in this case. 因此,我尝试使用Generics,但我不确定100%是否了解这种情况下的实现。 It's obvious when you want to do things like List and make a list of List but how do I apply it here? 当您想执行List并创建List列表时很明显,但是如何在此处应用它呢? I think I'm mainly confused about mocking up the code vs implementation, will everything just be T in the base and subclasses, than when I instantiate instances somewhere else like in the GUI that's when I specify the type of return I expect? 我想我对模范代码与实现的模棱两可感到困惑,是不是所有的东西都只是基类和子类中的T,而不是像我在GUI中那样实例化实例时(当我指定期望的返回类型时)? Than I think I understand. 比我想我理解。 So what I'm saying is when writing up the classes I only use T, never specify a Type and in the code where I instantiate instances that's when I specify a type and that's what the return type of doInBackground will be? 因此,我要说的是编写类时,我仅使用T,而从不指定Type,而在代码中实例化实例的代码(即指定类型时)即为doInBackground的返回类型?

I also want to be able to implement onPostExecute() generically because I will use a callback setup so the GUI can easily subscribe to when the call is finished and process the result, but the interfact will also have a generic for the onPostExecute(T response). 我还希望能够通用地实现onPostExecute(),因为我将使用回调设置,以便GUI可以在调用完成后轻松订阅并处理结果,但是交互操作也将具有onPostExecute(T响应)的通用名称。 )。 So I can create new instances, pass 'this', and when the async task is finished it will call the callback with the result and the callback can handle the appropriate type. 因此,我可以创建新实例,传递“ this”,并且当异步任务完成时,它将使用结果调用回调,并且回调可以处理适当的类型。

public class Base<T> extends AsyncTask<String, Integer, T> 
{   
    protected Callback callback = null; //interface implemented for processing response

    public Base setCallback(Callback callback){ this.callback = callback; return this; }

    @Override
    protected T doInBackground(String... uri) 
    {       
        //do http call
        String response = "";
        return response;  //raw string of server response
    }

    @Override
    final protected void onPostExecute(T result) 
    {    
        //no overrides, same every time
        if( callback != null )
        {
            callback.finished(result);  //forward generic result, but there it will be typed
        }
    }

public class JsonBase<T> extends Base<T>
{
    @Override
    protected T doInBackground(String... uri) 
    {       
        //this will be a JSONObject returned
        String result = (String)super.dpInBackground(uri); //gives me back a string
        return new JSONObject(result);                     //return a json object
    }    
} 

public class SpecializedBase<T> extends JsonBase<T>
{
    @Override
    protected T doInBackground(String... uri) 
    {       
        //this will be a List<String> returned
        //iterate over all json array strings and pass back
        return new List<String>();
    }
}

class FragmentFoo extends Fragment implements Callback
{
    @Override
    protected void onViewCreate(...)
    {
        //Example usage
        new JsonBase< JSONObject >().setCallback(this).execute("<url">);
        new SpecializedBase< List<String> >().setCallback(this).execute("");  //hard coded internally for example

    } 


    //Can we do something like this?  
    @Override
    protected void finished(JSONObject object)
    {
        //handle json response
    }

    @Override 
    protected void finished(List<String> strings)
    {
        //handle list of strings response
    }
}

interface Callback
{
    public <T> void finish(T response);      
}

The specialized sub classes of Async will be tailored to specific types, and return different types, and we want to handle those specialized type depending on where we are in the GUI and what we're doing. Async的特殊子类将针对特定类型进行量身定制,并返回不同的类型,并且我们希望根据我们在GUI中的位置以及正在执行的操作来处理这些特殊类型。 Otherwise all we can do is all the logic in the GUI or have another middle layer of wrappers...This is all just a primitive example illustrating my point and how we want this to work. 否则,我们所能做的就是GUI中的所有逻辑或具有另一个包装中间层……这仅仅是一个原始的例子,阐明了我的观点以及我们希望它如何工作。

Just kept T and anytime it complained about casting (T)response I just added a suppress warning. 只是保持T,只要它抱怨转换(T)响应,我都添加了禁止警告。 As long as I know what to expect in the specific callback and cast to that type, it's fine. 只要我知道在特定的回调中期望什么并转换为该类型,就可以了。 But could easily crash at runtime if I make a mistake and cast it to something else. 但是如果我犯了一个错误并将其转换为其他内容,则很容易在运行时崩溃。

It compiles, runs, and works. 它可以编译,运行和运行。 But doesn't seem like a clean appropriate solution. 但似乎不是一个干净合适的解决方案。

I know this is an old question but I've just come across it - used most of your solution and improved it a little to solve the issue you had. 我知道这是一个古老的问题,但我已经遇到了-使用您的大多数解决方案并对其进行了一些改进以解决您遇到的问题。

I'll just paste the code, but basically just type the list but rather than using it as a return value I use an integer static for the return value in the callback and create the list as a field of the asynctask object itself which is then accessed in the callback method. 我将粘贴代码,但是基本上只是键入列表,而不是将其用作返回值,而是在回调中使用整数静态值作为返回值,并将列表创建为asynctask对象本身的字段,然后在回调方法中访问。 (I also use a DatabaseLoaderParams for clarity) (为了清楚起见,我还使用了DatabaseLoaderParams)

public class DatabaseLoader<T> extends AsyncTask<DatabaseLoaderParams, Void, Integer> {


ArrayList<T> returnList;

protected DbLoaderCallback callback = null; //interface implemented for processing response

public DatabaseLoader setCallback(DbLoaderCallback callback){ this.callback = callback; return this; }


@Override
protected Integer doInBackground(DatabaseLoaderParams... params) {


//you have to give the object class to the asynctask     
ArrayList<T> mReturnList = getList(params[0].objectClass);

    try {
        // DB loading code

    } catch (Exception e) {
        e.printStackTrace();
    } catch (SQLException e) {

        e.printStackTrace();

        return 0;
    }


    // Done!
    returnList=mReturnList;

    return params[0].startId;
}

@Override
final protected void onPostExecute(Integer startId)
{

    if( callback != null && startId>0)
    {
        callback.onLoadFinished(startId);  //forward generic result, but there it will be typed
    }
}


private <T> ArrayList<T> getList(Class<T> requiredType) {
    return new ArrayList<T>();
}

In the activity: 在活动中:

@Override
public void onLoadFinished(int startId)
    {
        switch(startId){

        case INTEGER_STATIC:
            //check the type if you want but I don't bother
            for(DBObject dbObject : DBLoader.returnList){

.... ....

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 从位于异步任务doInBackGround中的回调返回一个值 - Return a value from callback which is situated in an async task doInBackGround 如何在使用泛型的方法中返回不同的类型? - How to return different types in a method using generics? 异步任务需要来自doInBackground的非数组返回对象,但会找到对象数组 - Async Task requires non-array return object from doInBackground but finds array of object 将字符串从异步任务的doInBackground传递到主线程 - Passing string from doInBackground of Async task to main thread 将参数从Activity传递到doInBackground方法,Async Task - Passing parameters from Activity to doInBackground method, Async Task doinbackground()在异步任务中无法正常工作 - doinbackground() in async task not working properly 在doInBackground方法中发生的异步任务#1 - Async task #1 occurring in the doInBackground method Android MultipartUploadRequest在异步任务doInBackground中不起作用 - Android MultipartUploadRequest not working in async task doInBackground 致命异常,异步任务的doInBackground()方法中的Runtimeerror - FATAL EXCEPTION, Runtimeerror in doInBackground() method of async task 异步任务执行doInBackground()时发生错误? - Async Task An error occured while executing doInBackground()?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM