AsyncTask startActivity 的意图不起作用(BINDER TRANSACTION 失败)

Posted

技术标签:

【中文标题】AsyncTask startActivity 的意图不起作用(BINDER TRANSACTION 失败)【英文标题】:Intent from AsyncTask startActivity not working (FAILED BINDER TRANSACTION) 【发布时间】:2016-06-13 09:29:08 【问题描述】:

我有以下AsyncTask。在 onPostExecute 方法中,我试图使用 Intent 开始另一个活动。但是,我注意到新活动没有开始,finish() 行被简单地称为关闭当前活动。我不知道这可能是什么原因。

   private void uploadImage(final String city, final String offset, final int currImage, final View itemView, final Animation animation) 
    class UploadImage extends AsyncTask<String, Void, String> 
        private Context context;

        public UploadImage(Context context)
            this.context=context;
        
      //  ProgressDialog loading;
        RequestHandler rh = new RequestHandler();

        @Override
        protected String doInBackground(String... params) 
            HashMap<String, String> data = new HashMap<>();
            data.put("city", city);
            data.put("offset",offset);
            String result = rh.sendPostRequest(SL_URL, data);

            return result;
        

        @Override
        protected void onPreExecute() 
            super.onPreExecute();
            //loading = ProgressDialog.show(SlideShow.this, "Uploading Image", "Please wait...", true, true);
        

        @Override
        protected void onPostExecute(String s) 
            super.onPostExecute(s);
           // loading.dismiss();
            JSONArray jsonArray = null;
            try 
                jsonArray = new JSONArray(s);
             catch (JSONException e) 
                e.printStackTrace();
            
            for (int i = 0; i < jsonArray.length(); i++) 
                try 
                    JSONObject a = jsonArray.getJSONObject(i);
                    imageDisplayerArrayList.add(new ImageDisplayer(a.getString("user_id"),a.getString("image"),a.getString("longitude"),a.getString("latitude"),a.getString("city"),a.getString("geo_name_id"),a.getString("description"),a.getString("score"),a.getString("Categories")));
                 catch (JSONException e) 
                    e.printStackTrace();
                
            
            itemView.clearAnimation();
            itemView.setVisibility(View.INVISIBLE);
            if (imageDisplayerArrayList.size() > 0) 
                Intent intent = new Intent(context, SlideShow.class);
                intent.putExtra("key",imageDisplayerArrayList);
                intent.putExtra("city", city);
                context.startActivity(intent);
                ((Activity) context).finish();
            
            else 
                Toast.makeText(getApplicationContext(), "No new content available", Toast.LENGTH_LONG)
                        .show();                



        
    UploadImage ui = new UploadImage(this);
    ui.execute(city);



PARCELABLE IMAGEDISPLAYER 类:

public class ImageDisplayer implements Parcelable 
private String user_id;
private String image;
private String longitude;

private ImageDisplayer(Parcel in) 
    this.user_id = in.readString();
    this.image = in.readString();
    this.longitude = in.readString();
    this.latitude = in.readString();
    this.city = in.readString();
    this.geo_name_id = in.readString();
    this.description = in.readString();
    this.score = in.readString();
    this.categories = in.readString();

public ImageDisplayer(String user_id, String image, String longitude, String latitude, String city, String geo_name_id, String description, String score, String categories) 
    this.user_id = user_id;
    this.image = image;
    this.longitude = longitude;
    this.latitude = latitude;
    this.city = city;
    this.geo_name_id = geo_name_id;
    this.description = description;
    this.score = score;
    this.categories = categories;


public String getUser_id() 

    return user_id;


public void setUser_id(String user_id) 
    this.user_id = user_id;


public String getImage() 
    return image;


public void setImage(String image) 
    this.image = image;


public String getLongitude() 
    return longitude;


public void setLongitude(String longitude) 
    this.longitude = longitude;


public String getLatitude() 
    return latitude;


public void setLatitude(String latitude) 
    this.latitude = latitude;


public String getCity() 
    return city;


public void setCity(String city) 
    this.city = city;


public String getGeo_name_id() 
    return geo_name_id;


public void setGeo_name_id(String geo_name_id) 
    this.geo_name_id = geo_name_id;


public String getDescription() 
    return description;


public void setDescription(String description) 
    this.description = description;


public String getScore() 
    return score;


public void setScore(String score) 
    this.score = score;


public String getCategories() 
    return categories;


public void setCategories(String categories) 
    this.categories = categories;


private String latitude;
private String city;
private String geo_name_id;
private String description;
private String score;
private String categories;

@Override
public int describeContents() 
    return 0;


@Override
public void writeToParcel(Parcel dest, int flags) 
    dest.writeString(user_id);
    dest.writeString(image);
    dest.writeString(longitude);
    dest.writeString(latitude);
    dest.writeString(city);
    dest.writeString(geo_name_id);
    dest.writeString(description);
    dest.writeString(score);
    dest.writeString(categories);


public static final Parcelable.Creator<ImageDisplayer> CREATOR
        = new Parcelable.Creator<ImageDisplayer>() 

    // This simply calls our new constructor (typically private) and
    // passes along the unmarshalled `Parcel`, and then returns the new object!
    @Override
    public ImageDisplayer createFromParcel(Parcel in) 
        return new ImageDisplayer(in);
    

    // We just need to copy this and change the type to match our class.
    @Override
    public ImageDisplayer[] newArray(int size) 
        return new ImageDisplayer[size];
    
;

幻灯片

public class SlideShow extends Activity 

private ArrayList<ImageDisplayer> imageDisplayerArrayList = new ArrayList<>();
private String city;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_slide_show);
    imageDisplayerArrayList = getIntent().getParcelableExtra("key");
    TextView time_rem = (TextView) findViewById(R.id.time_rem);
    time_rem.bringToFront();
    city = getIntent().getStringExtra("city");
    slideshow(imageDisplayerArrayList, 0, 0);



private void uploadImage2(final String city, final String offset, final int currImage) 
    class UploadImage extends AsyncTask<String, Void, String> 

        //ProgressDialog loading;
        RequestHandler rh = new RequestHandler();

        @Override
        protected String doInBackground(String... params) 
            HashMap<String, String> data = new HashMap<>();
            data.put("city", city);
            data.put("offset",offset);
            String result = rh.sendPostRequest(SL_URL, data);

            return result;
        

        @Override
        protected void onPreExecute() 
            super.onPreExecute();
           // loading = ProgressDialog.show(SlideShow.this, "Uploading Image", "Please wait...", true, true);
        

        @Override
        protected void onPostExecute(String s) 
            super.onPostExecute(s);
          //  loading.dismiss();
            JSONArray jsonArray = null;
            try 
                jsonArray = new JSONArray(s);
             catch (JSONException e) 
                e.printStackTrace();
            
            for (int i = 0; i < jsonArray.length(); i++) 
                try 
                    JSONObject a = jsonArray.getJSONObject(i);
                    imageDisplayerArrayList.add(new ImageDisplayer(a.getString("user_id"),a.getString("image"),a.getString("longitude"),a.getString("latitude"),a.getString("city"),a.getString("geo_name_id"),a.getString("description"),a.getString("score"),a.getString("Categories")));
                 catch (JSONException e) 
                    e.printStackTrace();
                
            


        
    UploadImage ui = new UploadImage();
    ui.execute(city);




public Bitmap ConvertToImage(String image)
        byte[] decodedByte = Base64.decode(image, 0);
        return BitmapFactory.decodeByteArray(decodedByte, 0, decodedByte.length);
    

public void slideshow(ArrayList<ImageDisplayer> a, final int currImage, final int offset) 
    ImageView imageView = (ImageView) findViewById(R.id.picturedisplay);
    int currphoto = 0;

    final long DELAY = 300; // milliseconds
    final long VIEW_TIME = 10000;
    Timer timer = new Timer();
    final TimerTask update_time = new TimerTask() 
        @Override
        public void run() 
            SlideShow.this.runOnUiThread(new Runnable() 
                @Override
                public void run() 
                    TextView time_rem = (TextView) findViewById(R.id.time_rem);
                    int timeRem = Integer.parseInt(time_rem.getText().toString());
                    timeRem--;
                    time_rem.setText(Integer.toString(timeRem));
                );
        ;
    timer.scheduleAtFixedRate(
            new TimerTask() 
                int i = currImage;
                int off = 0;
                @Override
                public void run() 
                    SlideShow.this.runOnUiThread(new Runnable() 
                        @Override
                        public void run() 
                            if (i < imageDisplayerArrayList.size()) 
                                TextView time_rem = (TextView) findViewById(R.id.time_rem);
                                time_rem.setText("10");
                                Bitmap myBitmap = ConvertToImage(imageDisplayerArrayList.get(i).getImage());
                                ImageView imageView = (ImageView) findViewById(R.id.picturedisplay);
                                imageView.setImageBitmap(myBitmap);
                                imageView.setScaleType(ImageView.ScaleType.FIT_XY);
                                Toast.makeText(getApplicationContext(),
                                Integer.toString(imageDisplayerArrayList.size()), Toast.LENGTH_LONG)
                               .show();
                                i++;
                                off = (int)(Math.rint(Math.ceil((double) i / 10) * 10));
                                if (i % 5 == 0 && i % 10 != 0) 
                                    uploadImage2(city,Integer.toString(off),i);
                                
                            
                            else 
                                update_time.cancel();
                                Intent i = new Intent(SlideShow.this,ViewScreen.class);
                                startActivity(i);
                                finish();
                            
                                                                  );
                


            ,
            DELAY,VIEW_TIME
    );
    timer.scheduleAtFixedRate(update_time, 0, 1000);




更新

这是由以下错误FAILED BINDER TRANSACTION !!! 引起的,因为我的图像数组列表超出了 1MB 的限制。有人可以帮我创建一个替代解决方案来在两个活动之间传递这个数组列表吗?

【问题讨论】:

是的,否则会显示 Toast,还会调用 finish()。我的 ImageDisplayer 类实现了 parcelable,这可能是一个问题吗? 只用这个startActivity(intent); 您能否通过设置断点来仔细检查 if 块是否已运行以防万一? 我以前用过,有同样的行为 我唯一能想到的另一件事是它是从内部类(异步任务)中调用的 【参考方案1】:

首先,您必须获取ParcelableArrayList imagesArrayList = getIntent().getParcelableArrayListExtra("key");

其次,你在slide show函数中做了太多的I/O工作,导致延迟

第三你正在做位图工作并在Ui Thread上显示位图,你必须将你的位图工作移出ui线程,它值得使用通用图像加载器https://github.com/nostra13/android-Universal-Image-Loader

希望这会有所帮助。

【讨论】:

【参考方案2】:

签出此代码。当你调用 asynctask 传递活动上下文时,就是这样。

Intent intent = new Intent(((Activity) context), SlideShow.class);
intent.putParcelableArrayListExtra("key",imageDisplayerArrayList);
intent.putExtra("city", city);
((Activity) context).startActivity(intent);
((Activity) context).finish();

现在您可以在另一个类似这样的活动中检索您的数组列表

imageDisplayerArrayList = getIntent().getParcelableArrayListExtra("key");

如果您在列表中传递位图,请不要这样做,只需在其中传递 url。

【讨论】:

【参考方案3】:

使用createSocketPair 创建一对ParcelFileDescriptors,并通过将对象放入意图中将其中一个对象传递给活动。然后,您可以通过从底层FileDescriptor 为包裹文件描述符创建File[Input|Output]Stream object 来传递数据。 (使用getFileDescriptor()获取FileDescriptor)

【讨论】:

以上是关于AsyncTask startActivity 的意图不起作用(BINDER TRANSACTION 失败)的主要内容,如果未能解决你的问题,请参考以下文章

startActivity 和 startSubActivity

Android startActivities()的使用

Context.startActivity() 与 Activity.startActivity() 究竟有什么不同?

Context.startActivity() 与 Activity.startActivity() 究竟有什么不同?

Context.startActivity() 与 Activity.startActivity() 究竟有什么不同?

Android 系统源码初步阅读之 activity 的 startActivity(intent) 与 非 activity 的 startActivity(...) 的不同