Android Asynctask:应用程序可能在其主线程上做了太多工作

时间:2016-12-22 09:51:13

标签: android multithreading android-fragments android-asynctask

我的代码有效,但我在监视器中有这个异常消息:I / Choreographer:跳过37帧!应用程序可能在其主线程上做了太多工作。

我理解这个错误消息意味着我在UI线程中做了很多重要的处理。问题是,对我来说,除了将假数据添加到ListView之外,我几乎没有在UI线程上做任何事情。我正在使用AsyncTask来发出API请求,这是我正在做的唯一“重型”工作,并且它不在主线程中。

我把所有代码放在这里,但我认为大部分代码都不是问题,因为当我评论我所有的假数据代码和对AsyncTask的调用时,我仍然有这个问题。所以我想问题更多的是关于我如何使用这个片段,因为我从未使用过它,所以我肯定在任何地方犯了错误......

//==== list_item_forecast.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:minHeight="?android:attr/listPreferredItemHeight"
    android:gravity="center_vertical"
    android:id="@+id/list_item_forecast_textview" />

//====fragment_main.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- using a FrameLayout because only one child element -->
<FrameLayout     xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/listview_forecast"/>
</FrameLayout>

//==== content_main.xml
<fragment     xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/fragment"
    android:name="com.example.android.sunshine.app.MainActivityFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:layout="@layout/fragment_main" />


//==== MainActivity
public class MainActivity extends AppCompatActivity implements ForecastRequest {

    private static String appId = "";
    // Will contain the raw JSON response as a string.
    String forecastJsonStr = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        // Get OpenWeather API key
        appId = getResources().getString(R.string.APPID);

        try {
            // Construct the URL for the OpenWeatherMap query
            // Possible parameters are avaiable at OWM's forecast     API page, at
        // http://openweathermap.org/API#forecast
            String url =     "http://api.openweathermap.org/data/2.5/forecast/daily?    q=94043&mode=json&units=metric&cnt=7&APPID=" + appId;
            OpenWeatherRequest request = new OpenWeatherRequest();
            request.response = this;
            request.execute(url);

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

    @Override
    public void requestDone(String jsonResponse) {
        forecastJsonStr = jsonResponse;
        Log.d(Constants.LOG_TAG,forecastJsonStr);
    }
}

//==== Interface used to get result from AsyncTask in MainActivity
public interface ForecastRequest {
    void requestDone(String output);
}

//==== The AsyncTask that make a request to OpenWeather API
public class OpenWeatherRequest extends AsyncTask<String, Integer, String> {
    // These two need to be declared outside the try/catch
    // so that they can be closed in the finally block.
    HttpURLConnection urlConnection = null;
    BufferedReader reader = null;
    // Will contain the raw JSON response as a string.
    String forecastJsonStr = null;
    public ForecastRequest response = null;

    protected void onPreExecute() {
        Log.d(Constants.LOG_TAG,"Fetching data...");
    }

    protected String doInBackground(String... urls) {
        try {
            URL url = new URL(urls[0]);

            // Create the request to OpenWeatherMap, and open the connection
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.connect();

            // Read the input stream into a String
            InputStream inputStream =     urlConnection.getInputStream();
            StringBuffer buffer = new StringBuffer();
            if (inputStream == null) {
                throw new Exception("No data");
            }
            reader = new BufferedReader(new InputStreamReader(inputStream));

            String line;
            while ((line = reader.readLine()) != null) {
                buffer.append(line + "\n");
            }

            if (buffer.length() == 0) {
                return null;
            }
            forecastJsonStr = buffer.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return forecastJsonStr;
    }

    protected void onPostExecute(String result) {
        response.requestDone(result);
    }
}

//==== The fragment
public class MainActivityFragment extends Fragment {

    private ArrayAdapter<String> mForecastAdapter;
    ArrayList<String> weekForecast;
    private ListView mListView;


    public MainActivityFragment() {

    }

    public void onViewCreated(View view, Bundle savedInstanceState) {


    }

    public View onCreateView(LayoutInflater inflater, ViewGroup     container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_main,     container, false);

        //=== Add fake data
        weekForecast = new ArrayList<>(Arrays.asList(
                "Today - Sunny - 88/63",
                "Tomorrow - Foggy - 70/40",
                "Weds - Cloudy - 72/63",
                "Thurs - Asteroids - 75/65",
                "Fri - Heavy Rain - 65/56",
                "Sat - HELP TRAPPED IN WEATHERSTATION - 60/51",
                "Sun - Sunny - 80/68")
        );

        mForecastAdapter = new ArrayAdapter<>(
                // The current context (this fragment parent activity)
                getActivity(),
                // ID of list item layout
                R.layout.list_item_forecast,
                // ID of the textview to populate
                R.id.list_item_forecast_textview,
                // Data
                weekForecast);

        mListView =     (ListView)rootView.findViewById(R.id.listview_forecast);
        mListView.setAdapter(mForecastAdapter);

        return rootView;
    }
}

1 个答案:

答案 0 :(得分:2)

我刚尝试使用手机而不是Android Studio模拟器,消息就消失了。所以问题来自模拟器而不是我的代码。