首页 > 解决方案 > java.lang.RuntimeException:执行doInBackground()时发生错误Singleton android错误

问题描述

我在将图像从 Android 应用程序发送到 API 时遇到问题。我收到“java.lang.RuntimeException:执行 doInBackground() 时发生错误”错误。请告诉我该怎么做。谢谢。

识别概念活动.java

package com.example.statistic.api.v2.activity;

import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import android.widget.ViewSwitcher;

import com.example.statistic.R;
import com.example.statistic.api.v2.App;
import com.example.statistic.api.v2.ClarifaiUtil;
import com.example.statistic.api.v2.adapter.RecognizeConceptsAdapter;

import java.util.Collections;
import java.util.List;

import butterknife.BindView;
import butterknife.OnClick;
import clarifai2.api.ClarifaiResponse;
import clarifai2.dto.input.ClarifaiImage;
import clarifai2.dto.input.ClarifaiInput;
import clarifai2.dto.model.ConceptModel;
import clarifai2.dto.model.output.ClarifaiOutput;
import clarifai2.dto.prediction.Concept;

import static android.view.View.GONE;
import static android.view.View.VISIBLE;

public final class RecognizeConceptsActivity extends BaseActivity {

  public static final int PICK_IMAGE = 100;

  // the list of results that were returned from the API
  @BindView(R.id.resultsList)
  RecyclerView resultsList;

  // the view where the image the user selected is displayed
  @BindView(R.id.image2)
  ImageView imageView;

  // switches between the text prompting the user to hit the FAB, and the loading spinner
  @BindView(R.id.switcher)
  ViewSwitcher switcher;

  // the FAB that the user clicks to select an image
  @BindView(R.id.fab)
  View fab;

  @NonNull
  private final RecognizeConceptsAdapter adapter = new RecognizeConceptsAdapter();

  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

  }

  @Override
  protected void onStart() {
    super.onStart();

    resultsList.setLayoutManager(new LinearLayoutManager(this));
    resultsList.setAdapter(adapter);
  }

  @OnClick(R.id.fab)
  void pickImage() {
    startActivityForResult(new Intent(Intent.ACTION_PICK).setType("image/*"), PICK_IMAGE);
  }

  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode != RESULT_OK) {
      return;
    }
    switch(requestCode) {
      case PICK_IMAGE:
        final byte[] imageBytes = ClarifaiUtil.retrieveSelectedImage(this, data);
        if (imageBytes != null) {
          onImagePicked(imageBytes);
        }
        break;
    }
  }

  private void onImagePicked(@NonNull final byte[] imageBytes) {
    // Now we will upload our image to the Clarifai API
    setBusy(true);

    // Make sure we don't show a list of old concepts while the image is being uploaded
    adapter.setData(Collections.<Concept>emptyList());

    new AsyncTask<Void, Void, ClarifaiResponse<List<ClarifaiOutput<Concept>>>>() {
      @Override
      protected ClarifaiResponse<List<ClarifaiOutput<Concept>>> doInBackground(Void... params) {
        // The default Clarifai model that identifies concepts in images
        final ConceptModel generalModel = App.get().clarifaiClient().getDefaultModels().generalModel();

        // Use this model to predict, with the image that the user just selected as the input
        return generalModel.predict()
            .withInputs(ClarifaiInput.forImage(ClarifaiImage.of(imageBytes)))
            .executeSync();
      }

      @Override
      protected void onPostExecute(ClarifaiResponse<List<ClarifaiOutput<Concept>>> response) {
        setBusy(false);
        if (!response.isSuccessful()) {
          showErrorSnackbar(R.string.error_while_contacting_api);
          return;
        }
        final List<ClarifaiOutput<Concept>> predictions = response.get();
        if (predictions.isEmpty()) {
          showErrorSnackbar(R.string.no_results_from_api);
          return;
        }
        adapter.setData(predictions.get(0).data());
        imageView.setImageBitmap(BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length));
      }

      private void showErrorSnackbar(@StringRes int errorString) {
        Snackbar.make(
            root,
            errorString,
            Snackbar.LENGTH_INDEFINITE
        ).show();
      }
    }.execute();
  }


  @Override
  protected int layoutRes() { return R.layout.activity_recognize; }

  private void setBusy(final boolean busy) {
    runOnUiThread(new Runnable() {
      @Override
      public void run() {
        switcher.setDisplayedChild(busy ? 1 : 0);
        imageView.setVisibility(busy ? GONE : VISIBLE);
        fab.setEnabled(!busy);
      }
    });
  }

}

应用程序.java

public class App extends Application {

  // In a real app, rather than attaching singletons (such as the API client instance) to your Application instance,
  // it's recommended that you use something like Dagger 2, and inject your client instance.
  // Since that would be a distraction here, we will just use a regular singleton.
  private static App INSTANCE;

  @NonNull
  public static App get() {
    final App instance = INSTANCE;
    if (instance == null) {
      throw new IllegalStateException("App has not been created yet!");
    }
    return instance;
  }

  @Nullable
  private ClarifaiClient client;

  @Override
  public void onCreate() {
    INSTANCE = this;
    client = new ClarifaiBuilder(getString(R.string.clarifai_api_key))
        // Optionally customize HTTP client via a custom OkHttp instance
        .client(new OkHttpClient.Builder()
            .readTimeout(30, TimeUnit.SECONDS) // Increase timeout for poor mobile networks

            // Log all incoming and outgoing data
            // NOTE: You will not want to use the BODY log-level in production, as it will leak your API request details
            // to the (publicly-viewable) Android log
            .addInterceptor(new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
              @Override
              public void log(String logString) {
                Timber.e(logString);
              }
            }).setLevel(HttpLoggingInterceptor.Level.BODY))
            .build()
        )
        .buildSync(); // use build() instead to get a Future<ClarifaiClient>, if you don't want to block this thread
    super.onCreate();

    // Initialize our logging
    Timber.plant(new Timber.DebugTree());
  }

  @NonNull
  public ClarifaiClient clarifaiClient() {
    final ClarifaiClient client = this.client;
    if (client == null) {
      throw new IllegalStateException("Cannot use Clarifai client before initialized");
    }
    return client;
  }
}

这是 logcat 错误

E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
                  Process: com.example.statistic, PID: 3451
                  java.lang.RuntimeException: An error occurred while executing doInBackground()
                      at android.os.AsyncTask$3.done(AsyncTask.java:325)
                      at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
                      at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
                      at java.util.concurrent.FutureTask.run(FutureTask.java:242)
                      at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
                      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
                      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
                      at java.lang.Thread.run(Thread.java:761)
                   Caused by: java.lang.IllegalStateException: App has not been created yet!
                      at com.example.statistic.api.v2.App.get(App.java:28)
                      at com.example.statistic.api.v2.activity.RecognizeConceptsActivity$1.doInBackground(RecognizeConceptsActivity.java:105)
                      at com.example.statistic.api.v2.activity.RecognizeConceptsActivity$1.doInBackground(RecognizeConceptsActivity.java:101)
                      at android.os.AsyncTask$2.call(AsyncTask.java:305)
                      at java.util.concurrent.FutureTask.run(FutureTask.java:237)
                      at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243) 
                      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
                      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
                      at java.lang.Thread.run(Thread.java:761) 

请告诉我该怎么做。谢谢

标签: javaandroidandroid-studio

解决方案


推荐阅读