AsyncTask问题,我做错了吗?

时间:2017-09-19 20:20:38

标签: java android json http android-asynctask

所以我得到了这个类,假设要获取一个json文件,然后将其解析成一个jsonObject,稍后将变成我将在我的片段中处理的Calendar实例列表。

目前,我正在doInBackground函数中执行请求和解析json对象,并返回Calendar实例列表。我几乎没有使用线程,也没有Android工作室的AsyncTask。

但是我收到以下错误(请参阅logcat)

09-19 20:08:46.614 13504-13504/com.abc.socke.abcE/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.abc.socke.abc, PID: 13504
    java.lang.ClassCastException: com.abc.socke.abc.Calendar cannot be cast to java.util.List
        at com.abc.socke.abc.CalendarFragment.onCreateView(CalendarFragment.java:46)
        at android.support.v4.app.Fragment.performCreateView(Fragment.java:2354)
        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1419)
        at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1740)
        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1809)
        at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:799)
        at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2580)
        at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2367)
        at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2322)
        at android.support.v4.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:2199)
        at android.support.v4.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:651)
        at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:145)
        at android.support.v4.view.ViewPager.populate(ViewPager.java:1236)
        at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:662)
        at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:624)
        at android.support.v4.view.ViewPager.setCurrentItem(ViewPager.java:605)
        at android.support.design.widget.TabLayout$ViewPagerOnTabSelectedListener.onTabSelected(TabLayout.java:2170)
        at android.support.design.widget.TabLayout.dispatchTabSelected(TabLayout.java:1165)
        at android.support.design.widget.TabLayout.selectTab(TabLayout.java:1158)
        at android.support.design.widget.TabLayout.selectTab(TabLayout.java:1128)
        at android.support.design.widget.TabLayout$Tab.select(TabLayout.java:1427)
        at android.support.design.widget.TabLayout$TabView.performClick(TabLayout.java:1537)
        at android.view.View$PerformClick.run(View.java:24697)
        at android.os.Handler.handleCallback(Handler.java:789)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6541)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

在我试图打电话的片段中,我指引我到这一行。

calendarEvents = (List<Calendar>) new Calendar().execute("https://api.myjson.com/bins/7cp25");

问题: 我究竟做错了什么?

我应该将我的http请求解析为JsonObject,然后在onPostExecute而不是doInBackground中创建我的Calendar实例吗?

尝试任何帮助人!

package com.MyAppName.Myname.MyAppName;

import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.util.Log;

import com.facebook.GraphResponse;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.simple.parser.JSONParser;


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;



public class Calendar extends AsyncTask<String, Void, List<Calendar>> {

    private String SUMMARY;
    private String DTSTART;
    private String data;
    public static final String REQUEST_METHOD = "GET";
    public static final int READ_TIMEOUT = 15000;
    public static final int CONNECTION_TIMEOUT = 15000;


    public String getEventSummary() {
        return SUMMARY;
    }

    public String getEventTime() {
        return DTSTART;
    }


    public Calendar(String eventName, String etimeStamp) {
        SUMMARY = eventName;
        DTSTART = etimeStamp;
    }

    public Calendar() {
    }


    @Override
    protected List<Calendar> doInBackground(String... params) {

        String inputUrl = params[0];
        Log.v("PARAMS[0] URL: ", inputUrl);


        try {
            URL url = new URL(inputUrl);

            HttpURLConnection connection = (HttpURLConnection) url.openConnection();

            //Set methods and timeouts
            connection.setRequestMethod(REQUEST_METHOD);
            connection.setReadTimeout(READ_TIMEOUT);
            connection.setConnectTimeout(CONNECTION_TIMEOUT);

            //Connect to our url
            connection.connect();

            InputStream inputStream = connection.getInputStream();

            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String line = "";
            while (line != null) {
                line = bufferedReader.readLine();
                data = data + line;

            }
        } catch (MalformedURLException e) {

        } catch (IOException e) {
            e.printStackTrace();
        }


        System.out.println("FETCHCALENDAREVENT");


        List<Calendar> allCalendarEvents = new ArrayList<Calendar>();

        try {
            JSONObject JsonData = new JSONObject(data);
            JSONArray data = JsonData.getJSONArray("VEVENT");

            for (int i = 0; i < data.length(); i++) {
                JSONObject jsonData = data.getJSONObject(i);
                String event_name = jsonData.getString("SUMMARY");
                String timeStamp = jsonData.getString("DTSTART;VALUE=DATE");


                Calendar calendarEvent = new Calendar(event_name, timeStamp);
                allCalendarEvents.add(calendarEvent);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

        Log.v("KOM HIT", "SKODKSODSODKOS");
        Log.v("all allCalendarEvents!", allCalendarEvents.get(2).getEventSummary());

        return allCalendarEvents;
    }


    protected void onPostExecute(List<Calendar>  allCalendarEvents) {
        super.onPostExecute(allCalendarEvents);
    }

}

更新:我尝试在onPostExecute中执行我的操作。不过这里有什么问题?:

ArrayList<String> calendarItems = new ArrayList<String>();

CalendarFragment.listView = CalendarFragment.view.findViewById(R.id.calendar_list_view);

for(int i = 0; i < allCalendarEvents.size(); i++){

    calendarItems.add(i, allCalendarEvents.get(i).getEventSummary().toString() + "\n" + allCalendarEvents.get(i).getEventTime().toString());
}

if(CalendarFragment.listView != null){
    ArrayAdapter<String> listViewAdapter = new ArrayAdapter<String>(
            CalendarFragment.context,
            android.R.layout.simple_list_item_2,
            calendarItems);
    CalendarFragment.listView.setAdapter(listViewAdapter);

我用CalendarFragment.context替换了getActivity(),以便更新正确的,我也调用了CalendarFragment.listview。我应该以另一种方式做到这一点吗?

3 个答案:

答案 0 :(得分:0)

在这一行

calendarEvents = (List<Calendar>) new Calendar().execute("https://api.myjson.com/bins/7cp25");

您正在尝试将Calendar instace(它是您执行()方法返回的AsyncTask实例)转换为List。这是完全不同的类型 - 这就是你得到ClassCastException的原因。

除此之外,您在代码中做了很奇怪的事情:您使用与结果类型相同的AsyncTasks列表来参数化AsyncTask任务。我非常怀疑这是你的意图。

答案 1 :(得分:0)

我认为你对AsyncTask有一点误解。

问题是您正在创建AsyncTask对象并尝试将其分配给List类型的对象。因此,抛出异常。

在AsyncTask doInBackground中,执行您的工作。工作完成后会返回return语句:

return allCalendarEvents;

该对象(在本例中为Calender对象列表)将返回到AsyncTask onPostExecute方法。

您希望对doInBackground中的列表执行有用的操作。您可以将其交还给调用.execute的班级,或者您可以执行其他操作,这取决于您。

答案 2 :(得分:0)

您想要的是将数据从AsyncTask类传递回调用者类。使用execute语句,您希望返回List。我假设你认为doInBackground()(在你的情况下是List)的返回值将由execute()调用返回。那是错的。这不是AsyncTask的工作原理。 doInBackground()的返回值作为结果赋予onPostExecute()。

你想要的是一个接口实现。 在您的日历类中

public interface IfaceCalendar {
    void onCalendaruResult(List<Calendar> list);
}

public IfaceCalendar listener;

public void SetListener(IfaceCalendar listener) {
    this.listener = listener;
}

因此,上面的代码设置了一个接口,可以异步地将结果返回给调用者片段。

您应该使用listener.onCalendarResult(list)来呼叫监听器。但是这个语句不应该在你的doInBackground()中。 doInBackground在后台线程上运行。您希望在UI线程中返回这些结果。因此,重写AsyncTask的onPostExecute()函数并通过那里返回结果。

@Override
public void onPostExecute(List<Calendar> list)
{
    if (listener != null) {
        listener.onCalendarResult(list);
    }
}

最后,您需要在执行任务

之前在片段中设置侦听器
Calendar c = new Calendar();
c.SetListener(this);
c.execute("https://api.myjson.com/bins/7cp25");

您可以覆盖片段中的onCalendarResult()函数,接收结果并执行您想要的任何操作。以下是它的实现方式:

@Override
public void onCalendarResult(List<Calendar> list) {
    // You have your list here. Do what you want with it
}