我有一个扩展异步任务的实用程序类。我将使用此调用在后台发出HTTP请求,但我还将有更多专门的子类来准备参数,标题,url来调用,所以我可以从GUI中删除更多常见的工作。
问题是我想要使用泛型。基础API类doInBackground将返回一个字符串,有一个更专业的Json子类,它将调用parent并返回一个JSONObject并对json响应进行一些解析,有专门的类扩展Json子类并返回自定义对象的List,所以上。原因是如果我们需要交换XML和XML处理,那么专门的子类将同时具有JSON和XML实现。这是因为我们正在重新使用几个不同的api。
所以我尝试使用Generics,但我并不是100%确定我理解这种情况下的实现。很明显,当你想做List之类的事情并列出List但是如何在这里应用它?我认为我主要是在模拟代码与实现之间混淆,在基本和子类中,一切都只是T,而不是像我在GUI中指定我期望的返回类型那样实例化其他地方的实例吗?比我想象的还要理解。所以我所说的是在编写类时我只使用T,从不指定类型,在代码中我实例化实例,当我指定类型时,这是doInBackground的返回类型是什么?
我还希望能够一般地实现onPostExecute()因为我将使用回调设置,因此GUI可以在调用完成时轻松订阅并处理结果,但是interfact也将具有onPostExecute的泛型(T回应)。所以我可以创建新实例,传递'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);
}
Async的专用子类将根据特定类型进行定制,并返回不同的类型,我们希望根据GUI中的位置和我们正在做的事情来处理这些特殊类型。否则我们所能做的只是GUI中的所有逻辑或者有另一个中间层的包装器......这只是一个原始的例子,说明了我的观点以及我们希望如何工作。
答案 0 :(得分:0)
只要保持T,任何时候它抱怨施放(T)响应我刚刚添加了抑制警告。只要我知道在特定的回调中会发生什么,并转换为该类型,那就没关系。但如果我犯了错误并将其转换为其他内容,则很容易在运行时崩溃。
它编译,运行和工作。但似乎不是一个干净的合适解决方案。
答案 1 :(得分:0)
我知道这是一个古老的问题,但我只是遇到过它 - 使用了大部分解决方案并对其进行了一些改进以解决您遇到的问题。
我只是粘贴代码,但基本上只需键入列表,而不是将其用作返回值,我使用整数静态作为回调中的返回值,并将列表创建为asynctask的字段对象本身,然后在回调方法中访问。 (为清晰起见,我还使用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>();
}
在活动中:
@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){
...