Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
626 views
in Technique[技术] by (71.8m points)

android - java.util.LinkedHashMap cannot be cast to DataList

I am trying to implement the server connections with retrofit library. Everything seems fine but when I receive the data on success callback it crashes with the below exception.

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to aandroid.com.retrofitframework.requestData.DataList
        at cuiserve.com.volleyframework.activity.RetrofitActivity$1.onDataReceived(RetrofitActivity.java:18)
        at cuiserve.com.volleyframework.httpConnection.ConnectionHelper.success(ConnectionHelper.java:44)
        at retrofit.CallbackRunnable$1.run(CallbackRunnable.java:45)
        at android.os.Handler.handleCallback(Handler.java:733)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:136)
        at android.app.ActivityThread.main(ActivityThread.java:5001)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
        at dalvik.system.NativeStart.main(Native Method)

here is the activity class making the server calls

public class RetrofitActivity extends SuperActivity {


    private ConnectionHelper.ServerListener<DataList> httpListener = new ConnectionHelper.ServerListener<DataList>() {

        @Override
        public void onDataReceived(DataList data) {
            hideProgressBar();
            Log.d("ANSH",data.getBalance());
        }

        @Override
        public void onErrorReceived(String errorMsg) {
            hideProgressBar();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        showProgressBar();

        ConnectionHelper<DataList> helper = new ConnectionHelper<DataList>(HttpRequestConstant.LOGIN_REQUEST,httpListener);
        helper.getResponse();
    }

    @Override
    public View getLayoutResource() {
        return null;
    }

    @Override
    protected void internetAvailable() {

    }
}

ConnectionHelper.class making the request

public class ConnectionHelper<T> implements Callback<T> {


    private int requestType;
    private ServerListener<T> listener;

    public ConnectionHelper(int requestType, ServerListener listener) {
        this.requestType = requestType;
        this.listener = listener;
    }

    public void getResponse() {
        switch (requestType) {
            case HttpRequestConstant.LOGIN_REQUEST:
                IServerConnection<T> connection = restAdapter.create(IServerConnection.class);
                connection.login(this);
                break;
        }
    }


    RestAdapter restAdapter = new RestAdapter.Builder()
            .setEndpoint("http://www.json-generator.com/api")
            .setLogLevel(RestAdapter.LogLevel.FULL)
            .setConverter(new JacksonConverter(Mapper.get()))
            .build();

    @Override
    public void success(T t, Response response) {
        listener.onDataReceived(t);
        // success callback false here with the exception
        // as ClassCastException and says LinkedHashMap can not be cast to DataList(which i pass as class that the response has to be mapped to)
    }

    @Override
    public void failure(RetrofitError error) {

    }


    public interface ServerListener<T> {

        public void onDataReceived(T data);

        public void onErrorReceived(String errorMsg);

    }
}

The interface and the method with retrofit annotation

public interface IServerConnection<T> {

    @GET(HttpRequestConstant.JACKSON_FETCH)
    void login(Callback<T> cb);
}

The custom JacksonConverter which is my suspicion

public class JacksonConverter implements Converter {
    private ObjectMapper mapper = new ObjectMapper();

    public JacksonConverter(ObjectMapper objectMapper) {
        this.mapper = objectMapper;
    }

    @Override
    public Object fromBody(TypedInput body, Type type) throws ConversionException {
        JavaType javaType = mapper.getTypeFactory().constructType(type);

        try {
            return mapper.readValue(body.in(), javaType);
        } catch (IOException e) {
            throw new ConversionException(e);
        }
    }

    @Override
    public TypedOutput toBody(Object object) {
        try {
            String charset = "UTF-8";
            String json = mapper.writeValueAsString(object);
            return new JsonTypedOutput(json.getBytes(charset));
        } catch (IOException e) {
            throw new AssertionError(e);
        }
    }

    private static class JsonTypedOutput implements TypedOutput {
        private final byte[] jsonBytes;

        JsonTypedOutput(byte[] jsonBytes) {
            this.jsonBytes = jsonBytes;
        }

        @Override
        public String fileName() {
            return null;
        }

        @Override
        public String mimeType() {
            return "application/json; charset=UTF-8";
        }

        @Override
        public long length() {
            return jsonBytes.length;
        }

        @Override
        public void writeTo(OutputStream out) throws IOException {
            out.write(jsonBytes);
        }
    }
}

and the DataList

package cuiserve.com.volleyframework.requestData;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

/**
 * Created by ansh on 5/4/15.
 */


@JsonIgnoreProperties(ignoreUnknown = true)
public class DataList extends SomeClass{

    private String _id;

    private int index;

    private String guid;

    private boolean isActive;

    private String balance;

    private String picture;

    private int age;

    public String get_id() {
        return _id;
    }

    public void set_id(String _id) {
        this._id = _id;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    public String getGuid() {
        return guid;
    }

    public void setGuid(String guid) {
        this.guid = guid;
    }

    public boolean isActive() {
        return isActive;
    }

    public void setActive(boolean isActive) {
        this.isActive = isActive;
    }

    public String getBalance() {
        return balance;
    }

    public void setBalance(String balance) {
        this.balance = balance;
    }

    public String getPicture() {
        return picture;
    }

    public void setPicture(String picture) {
        this.picture = picture;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

Now the problem is when i do it without using generics(which i have done in the code) things work fine and don't give any exception but in case of generics it fails.

Why am I getting LinkedHashMap classCastException where nothing is related to that in my code.Please help.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

By using a generic parameter the actual type information is completely lost to the runtime and cannot be inferred. It essentially ends up being the same as Object. When Gson sees that you want an Object type, it uses a Map to place the JSON information in. This way, if you re-serialize that object instance the data will be retained.

You cannot use generic interfaces with Retrofit. An exception has been added when you try to do this rather than letting it fail in this manner for the next release.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...