【问题标题】:AsyncTask issue, am I doing it wrong?AsyncTask 问题,我做错了吗?
【发布时间】:2017-09-19 20:20:38
【问题描述】:

所以我得到了这个类,它假设获取一个 jsonfile,然后将其解析为一个 jsonObject,该对象稍后将转换为我将在我的片段中处理的日历实例列表。

目前,我正在 doInBackground 函数中对 json 对象进行请求和解析,并返回一个日历实例列表。我几乎没有在 android studios 中使用线程和 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)

这将我引导到我试图拨打此电话的 Fragment 中的这一行。

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

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

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

请尝试寻求任何帮助!

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。我应该以其他方式来做这件事吗?

【问题讨论】:

  • calendarEvents = (List&lt;Calendar&gt;) new Calendar().execute 使用回调将分配移动到 onPostExecute 是错误的。如果您需要帮助,只需告诉您制作一个小样本即可。

标签: java android json http android-asynctask


【解决方案1】:

在这一行

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

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

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

【讨论】:

  • 可以将 HTTP 请求与日历类实例分开的一种解决方案。那是在我的片段中的 onCreate 我首先调用 HTTP 类来获取结果,然后我只需调用我的 Calendar 类并将其转换为 json 对象并返回该类实例的列表?
【解决方案2】:

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

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

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

return allCalendarEvents;

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

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

【讨论】:

  • 可以将 HTTP 请求与日历类实例分开的一种解决方案。那是在我的片段中的 onCreate 我首先调用 HTTP 类来获取结果,然后我只需调用我的 Calendar 类并将其转换为 json 对象并返回该类实例的列表?
【解决方案3】:

你想要的是将数据从 AsyncTask 类传回给你的调用者类。使用您的执行语句,您希望返回一个列表。我假设您认为 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
}

【讨论】:

  • 请回复。我正在考虑尽快尝试您的解决方案。可以将 HTTP 请求与日历类实例分开的一种解决方案。那是在我的片段中的 onCreate 我首先调用 HTTP 类来获取结果,然后我只需调用我的 Calendar 类并将其转换为 json 对象并返回该类实例的列表?
  • 即使你这样做了,你也无法保证 Http 请求什么时候完成。学习接口并将它们与 AsyncTask 一起使用是一个很好的方法,并且稍后也会帮助您。所以我建议只是吸吮它并学习它:P。了解 AsyncTask 和接口的基础知识,您就可以很好地实现任何后台操作,而不是在代码中添加 hack。
  • 这是真的!学习结构比编写意大利面条代码更好:P 一个问题:onCalendaruResult 是否应该在我的 Fragment 或 Calendar 类中实现?它应该做什么和包含什么?
  • 它应该在你的片段中。编辑了如何覆盖它的答案。
  • 它说 Method 不会覆盖其超类。我认为这背后的原因是因为我还没有在我的片段 CalendarFragment.java 文件中定义 onCalendarResult 。在我的 onCreate 方法中,我需要有我的列表。不幸的是 onCalendarResult() 不能在 onCreate 中调用,因为我没有 List 那里。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-04
  • 2016-08-01
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多