Android java binder FAILED BINDER TRANSACTION

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25513188/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 00:32:22  来源:igfitidea点击:

Android java binder FAILED BINDER TRANSACTION

javaandroidlistview

提问by Gzuz07

I have the next problem, I'm creating a list view a custom adapter, I am downloading the data for the adapter from a JSON url (text and image urls) using an async task, then I set the adapter to the list, I download the images using picasso library, now my app works fine, it doesn't crashes but when I start another activity i get this:

我有下一个问题,我正在创建一个列表视图自定义适配器,我正在使用异步任务从 JSON url(文本和图像 url)下载适配器的数据,然后我将适配器设置为列表,我使用 picasso 库下载图像,现在我的应用程序工作正常,它不会崩溃,但是当我开始另一个活动时,我得到了这个:

E/JavaBinder﹕ !!! FAILED BINDER TRANSACTION !!!

E/JavaBinder:!!!失败的绑定交易!!!

I get the error even if the new activity is empty, I'm using a moto G. I have analyzed the heap with DDMS and Eclipse MAT and I haven't find if my code is causing memory leaks. Changing from one activity to another multiple times I get this in the logcat:

即使新活动为空,我也会收到错误消息,我使用的是 moto G。我已经使用 DDMS 和 Eclipse MAT 分析了堆,但我没有发现我的代码是否导致内存泄漏。我在 logcat 中多次从一个活动更改为另一个活动:

09-04 10:37:54.827  30603-30603/mx.f403.whimlike E/JavaBinder﹕ !!! FAILED BINDER TRANSACTION !!!
09-04 10:38:01.793  30603-30603/mx.f403.whimlike D/dalvikvm﹕ GC_FOR_ALLOC freed 1178K, 24% free 13642K/17876K, paused 21ms, total 21ms
09-04 10:38:02.939  30603-30603/mx.f403.whimlike E/JavaBinder﹕ !!! FAILED BINDER TRANSACTION !!!
09-04 10:38:07.235  30603-30603/mx.f403.whimlike D/dalvikvm﹕ GC_FOR_ALLOC freed 1008K, 24% free 13657K/17876K, paused 20ms, total 20ms
09-04 10:38:14.484  30603-30603/mx.f403.whimlike E/JavaBinder﹕ !!! FAILED BINDER TRANSACTION !!!
09-04 10:38:15.497  30603-30603/mx.f403.whimlike D/dalvikvm﹕ GC_FOR_ALLOC freed 1065K, 24% free 13656K/17876K, paused 18ms, total 18ms
09-04 10:38:16.371  30603-30603/mx.f403.whimlike E/JavaBinder﹕ !!! FAILED BINDER TRANSACTION !!!
09-04 10:38:16.688  30603-30603/mx.f403.whimlike D/dalvikvm﹕ GC_FOR_ALLOC freed 1007K, 24% free 13628K/17876K, paused 19ms, total 19ms
09-04 10:38:17.491  30603-30603/mx.f403.whimlike E/JavaBinder﹕ !!! FAILED BINDER TRANSACTION !!!
09-04 10:38:17.781  30603-30603/mx.f403.whimlike D/dalvikvm﹕ GC_FOR_ALLOC freed 1020K, 24% free 13653K/17876K, paused 27ms, total 27ms

As you can see the memory heap doesn't increase, but I get the error the same way.

如您所见,内存堆没有增加,但我以同样的方式得到错误。

I don't think the problem is in the bitmaps I'm downloading for the first activity because I commented all the lines of code where the bitmaps are involved, I also commented the asynctasks and the problem continues arising, anyway I'm going to let the adapter here:

我不认为问题出在我为第一个活动下载的位图中,因为我评论了涉及位图的所有代码行,我还评论了 asynctasks 并且问题继续出现,无论如何我要让适配器在这里:

    class ClientListAdapter extends BaseAdapter {

    private Context context;
    private ClientList clients;
    private ClientList arrayList;

    public ClientListAdapter(Context context, ClientList clients) {
        this.context = context;
        this.clients = clients;
        this.arrayList = new ClientList();
        this.arrayList.addAll(clients);
    }

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Client client = clients.get(position);
        ClientHolder clientHolder = new ClientHolder();

        if(convertView == null){

            LayoutInflater inflater = ((Activity)context).getLayoutInflater();
            convertView = inflater.inflate(R.layout.client_list_item,parent,false);

            clientHolder.clientName = (TextView) convertView.findViewById(R.id.client_name);
            clientHolder.clientImage = (ImageView) convertView.findViewById(R.id.client_image);

            convertView.setTag(clientHolder);
        }
        else{
            clientHolder = (ClientHolder) convertView.getTag();
        }

        if (client != null) {
            clientHolder.clientImage.setImageResource(R.drawable.ic_launcher);
            Picasso.with(context).load(client.getClientImageUrl()).into(clientHolder.clientImage);
            clientHolder.clientName.setText(client.getName());
        }
        return convertView;
    }

    static class ClientHolder{
        TextView clientName;
        ImageView clientImage;
    }

I downloaded the Eclipse MAT and it shows the leak possible causes, but I don't understand very well what that means, this is the result of the Eclipse MAT:

我下载了 Eclipse MAT,它显示了泄漏的可能原因,但我不太明白这意味着什么,这是 Eclipse MAT 的结果:

**Problem Suspect 1**

The class "android.content.res.Resources", loaded by "<system class loader>", occupies 2,968,072 (14.65%) bytes. The memory is accumulated in one instance of "android.util.LongSparseArray[]" loaded by "<system class loader>".

Keywords
android.util.LongSparseArray[]
android.content.res.Resources


  **Problem Suspect 2**

16 instances of "byte[]", loaded by "<system class loader>" occupy 5,860,824 (28.92%) bytes. 

Biggest instances:
?byte[1705600] @ 0x432a2f28 ..........................................y...x...v...v...v...u...t...t...t...t...t...t...t...t...s...s...s...s...r...r...q...q...n...n...n...n...m...m...l...l...l...l...l...l...k...k...j...j...[...[...\...[...\...Y...\...Z...[...Z...\...Z...Z...Y...Z...Z.... - 1,705,616 (8.42%) bytes. 
?byte[1536000] @ 0x42715a48 ................................................................................................................................................................................................................................................................... - 1,536,016 (7.58%) bytes. 
?byte[1500000] @ 0x43751fd0 ..w...x...{...|...|...{...y...x...t...v...s...t...l...h...`...^...J...H...F...F...H...J...I...H...F...F...E...D...C...A...A...@...E...E...E...E...E...E...E...E...F...F...F...E...E...D...D...D...;...;...;...;...;...;...;...;...;...9..~8...9...;...<...;...9.... - 1,500,016 (7.40%) bytes. 
?byte[788544] @ 0x42ab6ab8 ................................................................................................................................................................................................................................................................... - 788,560 (3.89%) bytes. 
?byte[293304] @ 0x426c7e78 ....LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL... - 293,320 (1.45%) bytes. 


Keywords
byte[]

  **Problem Suspect 3**

20 instances of "android.graphics.Bitmap", loaded by "<system class loader>" occupy 3,213,736 (15.86%) bytes. 

Biggest instances:
?android.graphics.Bitmap @ 0x4227b8f0 - 1,127,584 (5.56%) bytes. 
?android.graphics.Bitmap @ 0x42998158 - 640,064 (3.16%) bytes. 
?android.graphics.Bitmap @ 0x42cbf0a8 - 367,296 (1.81%) bytes. 
?android.graphics.Bitmap @ 0x42d21008 - 360,064 (1.78%) bytes. 
?android.graphics.Bitmap @ 0x428e01f8 - 293,368 (1.45%) bytes. 


Keywords
android.graphics.Bitmap


  **Problem Suspect 4**

168 instances of "android.graphics.NinePatch", loaded by "<system class loader>" occupy 2,170,152 (10.71%) bytes. These instances are referenced from one instance of "java.lang.Object[]", loaded by "<system class loader>"

Keywords
java.lang.Object[]
android.graphics.NinePatch

 **Hint 1**

The problem suspects 1 and 4 may be related, because the reference chains to them have a common beginning.

In some blogs I've read that you shouldn't hold references to activities, maybe could be that but I don't know in which part of my code applies and how to solve it, Here is my Main Activity and the fragment where I think the problem is:

在我读过的一些博客中,你不应该引用活动,也许是这样,但我不知道我的代码的哪一部分适用以及如何解决它,这是我的主要活动和我所在的片段认为问题是:

public class MainActivity extends ActionBarActivity implements LoggedInFragment.SetUserInfoInterface{

    // Constant keys for passing data between Activities
    public static final String CLIENTLINK = "ClientLink";
    public static final String CLIENTID = "ClientId";
    public static final String DEBATEFLAG = "DebateFlag";

    public static final String USERID = "UserId";

    public static final String SHOW_EMAIL_ASSIGN_DIALOG_ADVICE = "Show email assign dialog advice";

    // Constant id's for showing logged in and logged out fragments
    private static final int LOGGED_OUT = 0;
    private static final int LOGGED_IN = 1;
    private static final int SETTINGS = 2;
       private static final int FRAGMENT_COUNT = SETTINGS + 1;

    private Fragment[] fragments = new Fragment[FRAGMENT_COUNT];

    // Flag to know if a fragment is resumed
    private boolean isResumed = false;

    public String userId;

    // Creates a UiHelper to get a call when a session changes
    private UiLifecycleHelper uiHelper;

    // Creates a callback that does shows a fragment depending of the state of the session, this
    // callback calls the function onSessionStateChange.
    private Session.StatusCallback callback =
            new Session.StatusCallback() {
                @Override
                public void call(Session session,
                                 SessionState state, Exception exception) {
                    onSessionStateChange(session, state, exception);
                }
            };

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

        // Set uiHelper to get the callback created previously
        uiHelper = new UiLifecycleHelper(this, callback);
        uiHelper.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        FragmentManager fm = getSupportFragmentManager();
        fragments[LOGGED_OUT] = fm.findFragmentById(R.id.loggedOutFragment);
        fragments[LOGGED_IN] = fm.findFragmentById(R.id.loggedInFragment);
        fragments[SETTINGS] = fm.findFragmentById(R.id.customSettingsFragment);

        FragmentTransaction transaction = fm.beginTransaction();
        for(Fragment fragment : fragments){
            transaction.hide(fragment);
        }
        transaction.commit();
    }

    public boolean isOnline() {
        ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo netInfo = cm.getActiveNetworkInfo();
        return (netInfo != null && netInfo.isConnected());
    }

    private void showFragment(int fragmentIndex, boolean addToBackStack) {
        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction transaction = fm.beginTransaction();
        for (int i = 0; i < fragments.length; i++) {
            if (i == fragmentIndex) {
                transaction.show(fragments[i]);
            } else {
                transaction.hide(fragments[i]);
            }
        }
        if (addToBackStack) {
            transaction.addToBackStack(null);
        }
        transaction.commit();
    }

    private void onSessionStateChange(Session session, SessionState state, Exception exception) {
        // Only make changes if the activity is visible
        if (isResumed) {
            FragmentManager manager = getSupportFragmentManager();
            // Get the number of entries in the back stack
            int backStackSize = manager.getBackStackEntryCount();
            // Clear the back stack
            for (int i = 0; i < backStackSize; i++) {
                manager.popBackStack();
            }
            if (state.isOpened()) {
                // If the session state is open:
                // Show the authenticated fragment
                showFragment(LOGGED_IN, false);
            } else if (state.isClosed()) {
                // If the session state is closed:
                // Show the login fragment
                showFragment(LOGGED_OUT, false);
            }
        }
    }

    @Override
    protected void onResumeFragments() {
        super.onResumeFragments();
        Session session = Session.getActiveSession();
        if (session != null && session.isOpened()) {
            // if the session is already open,
            // try to show the LoggedInFragment
            showFragment(LOGGED_IN, false);
        } else {
            // otherwise present the LoggedOutFragment
            // and ask the person to login.
            showFragment(LOGGED_OUT, false);
        }
    }

    public void closeSession(){
        Session session = Session.getActiveSession();
        session.close();
    }

    @Override
    public void onResume() {
        super.onResume();
        uiHelper.onResume();
        isResumed = true;
    }

    @Override
    public void onPause() {
        super.onPause();
        uiHelper.onPause();
        isResumed = false;
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        uiHelper.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        uiHelper.onDestroy();
    }

    public void showPromptNoInternet() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);

        builder.setPositiveButton(R.string.button_accept, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
        });

        builder.setTitle(getString(R.string.no_internet_dialog_title));
        builder.setMessage(getString(R.string.no_internet_dialog_message));

        AlertDialog dlg = builder.create();
        dlg.show();
    }

    public void showSortDialog(){
        FragmentManager fm = getSupportFragmentManager();
        final LoggedInFragment loggedInFragment = (LoggedInFragment)fm.findFragmentById(R.id.loggedInFragment);
        ArrayAdapter<String> sorting_forms = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1);
        sorting_forms.add(getString(R.string.sort_ascending_order));
        sorting_forms.add(getString(R.string.sort_descending_order));
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("Ordenar")
                    .setAdapter(sorting_forms, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            switch (which){
                                case 0:
                                    loggedInFragment.sortClientList("ascend");
                                    break;
                                case 1:
                                    loggedInFragment.sortClientList("descend");
                                    break;
                            }
                        }
                    });
            AlertDialog dlg = builder.create();
        dlg.show();
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu items for use in the action bar
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.settings, menu);

        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction transaction = fm.beginTransaction();

        switch(item.getItemId()) {
            case R.id.settings:
                transaction.show(fragments[SETTINGS]);
                transaction.hide(fragments[LOGGED_IN]);
                transaction.addToBackStack(null);
                transaction.commit();
                return true;
            case R.id.action_my_coupons:
                Intent i = new Intent(this, CouponListActivity.class);
                i.putExtra(USERID, userId);
                startActivity(i);
                return true;
            case R.id.view_recent_promotions:
                Intent recentPromoListActivityIntent = new Intent(this, RecentPromotionListActivity.class);
                recentPromoListActivityIntent.putExtra(USERID, userId);
                recentPromoListActivityIntent.putExtra(MainActivity.DEBATEFLAG,false);
                startActivity(recentPromoListActivityIntent);
                return true;
            case R.id.action_sort:
                showSortDialog();
                return true;

            default:
                super.onOptionsItemSelected(item);
        }
        return false;
    }

    @Override
    public void setUserId(String userId) {
        this.userId = userId;
    }
}

And the fragment:

和片段:

public class LoggedInFragment extends Fragment implements LoadClientsAsyncTask.ClientAsyncResponse, View.OnClickListener{

    public String userId;
    private ClientList clients;
    private ClientListAdapter adapter;
    private ListView clientList;

    private UiLifecycleHelper uiHelper;
    private Session.StatusCallback callback = new Session.StatusCallback() {
        @Override
        public void call(Session session, SessionState state, Exception exception) {
            onSessionStateChange(session, state, exception);
        }
    };

    public SetUserInfoInterface mCallback = null;

    public interface SetUserInfoInterface {
        public void setUserId(String userId);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception
        try {
            mCallback = (SetUserInfoInterface) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnHeadlineSelectedListener");
        }
    }

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

        uiHelper = new UiLifecycleHelper(getActivity(),callback);
        uiHelper.onCreate(savedInstanceState);

        Session session = Session.getActiveSession();
        if(session != null){
            makeMeRequest(session);
        }
        Log.d("panda", "Logged in Creado");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        final View view = (inflater.inflate(R.layout.logged_in, container, false));
        LinearLayout debateLayout = (LinearLayout) view.findViewById(R.id.debate_layout);
        debateLayout.setOnClickListener(this);

        return view;
    }

    @Override
    public void onClick(View v) {
        Intent debatePromoListActivityIntent = new Intent(getActivity(), RecentPromotionListActivity.class);
        debatePromoListActivityIntent.putExtra(MainActivity.USERID, userId);
        debatePromoListActivityIntent.putExtra(MainActivity.DEBATEFLAG,true);
        startActivity(debatePromoListActivityIntent);
    }

    private void onSessionStateChange(Session session, SessionState state, Exception exception){
        // If the session is opened and is not null
        if (session != null && session.isOpened() && ((MainActivity)getActivity()).isOnline()) {
            // Get the user's data
            makeMeRequest(session);
        }
    }

    private void makeMeRequest(final Session session){

        final Request request = Request.newMeRequest(session, new Request.GraphUserCallback() {

            @Override
            public void onCompleted(GraphUser user, Response response) {

                if (session == Session.getActiveSession()) {
                    if (user != null) {
                        userId = user.getId();
                        String userName = user.getName();
                        String userEmail = user.getProperty("email").toString();
                        mCallback.setUserId(userId);
                        postData(userId, userName, userEmail);
                    }
                }
            }
        });
        request.executeAsync();
    }

    private void setListListener(ClientList clients) {
        if (ApplicationCheckActivityVisibility.isActivityVisible()) {
            adapter = new ClientListAdapter(getActivity(),R.layout.client_list_item,clients);
            View view = getView();
            clientList = (ListView) view.findViewById(R.id.clients_list);
            clientList.setAdapter(adapter);
            clientList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> adapter, View view, int position, long id) {
                    Client chosenClient = (Client) clientList.getItemAtPosition(position);
                    String clientLink = chosenClient.getLink();
                    String clientId = chosenClient.getId();
                    Intent i = new Intent(getActivity(), PromoListActivity.class);
                    i.putExtra(MainActivity.CLIENTLINK, clientLink);
                    i.putExtra(MainActivity.CLIENTID, clientId);
                    i.putExtra(MainActivity.USERID, userId);
                    startActivity(i);
                }
            });
        }
    }

    public void sortClientList(String form){
        if(form.matches("ascend")){
            Collections.sort(clients, ClientAscComparator);
        }
        else if(form.matches("descend")){
            Collections.sort(clients, ClientDescComparator);
        }
        adapter.notifyDataSetChanged();
    }

    public Comparator<Client> ClientAscComparator = new Comparator<Client>() {

        public int compare(Client client1, Client client2) {

            String clientName1 = client1.getName();
            String clientName2 = client2.getName();

            return clientName1.compareTo(clientName2);
        }
    };

    public Comparator<Client> ClientDescComparator = new Comparator<Client>() {

        public int compare(Client client1, Client client2) {

            String clientName1 = client1.getName();
            String clientName2 = client2.getName();

            return clientName2.compareTo(clientName1);
        }
    };

    @Override
    public void processFinish(ClientList clients) {

        View view = getView();

        if(view != null) {
            RelativeLayout loadingPanel = (RelativeLayout) view.findViewById(R.id.loading_panel);
            loadingPanel.setVisibility(View.GONE);
        }

        if(clients != null){
            this.clients = clients;
            setListListener(clients);
        }
        else{
            Toast.makeText(getActivity(), R.string.no_restaurants_right_now, Toast.LENGTH_SHORT).show();
        }
    }

    public void postData(String userId,String userName,String userEmail){
        if(((MainActivity)getActivity()).isOnline()) {
            HttpPostAsyncTask httpPostAsyncTask = new HttpPostAsyncTask(userId, userName, userEmail, getFragmentManager());
            httpPostAsyncTask.execute();
        }
        else
        {
            ((MainActivity)getActivity()).showPromptNoInternet();
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        uiHelper.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public void onResume() {
        super.onResume();

        ApplicationCheckActivityVisibility.activityResumed();

        if(((MainActivity)getActivity()).isOnline()) {
            LoadClientsAsyncTask asyncTask = new LoadClientsAsyncTask();
            asyncTask.delegate = this;
            asyncTask.execute();
        }
        else
        {
            ((MainActivity)getActivity()).showPromptNoInternet();
        }
        uiHelper.onResume();
    }

    @Override
    public void onSaveInstanceState(Bundle bundle) {
        super.onSaveInstanceState(bundle);
        uiHelper.onSaveInstanceState(bundle);
    }

    @Override
    public void onPause() {
        super.onPause();
        ApplicationCheckActivityVisibility.activityPaused();
        uiHelper.onPause();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        uiHelper.onDestroy();
    }
}

The error arises when the app calls an intent and gets in the other activities, so I think that I am not finishing cleaning the memory of the first activity correctly and the heap acumulates in the two of them causing the error. But as you saw in the logcat, the memory heap is stable and doesn't increase when I change from one activity to another. Sometimes I get this too:

当应用程序调用一个意图并进入其他活动时会出现错误,所以我认为我没有正确完成第一个活动的内存清理,并且堆在它们两个中累积导致错误。但是正如您在 logcat 中看到的那样,内存堆是稳定的,当我从一个活动更改为另一个活动时不会增加。有时我也会得到这个:

I/dalvikvm﹕ threadid=3: reacting to signal 3

UPDATE: Another thing I observed is that I run the code in a samsung ACE, a Moto Razr Z3 and a Galaxy Tab 2 and the error doesn't appear even these devices have less memory than the Moto g, could this be an error or bug on the moto g?

更新:我观察到的另一件事是,我在三星 ACE、Moto Razr Z3 和 Galaxy Tab 2 中运行代码,即使这些设备的内存比 Moto g 少,也没有出现错误,这可能是错误还是moto g 上的错误?

回答by athor

There are some limitations as to how much data a bundle can contain. If your bundle or intent extras are too large you can get this error. Are you passing data into a bundle at all?

一个包可以包含多少数据有一些限制。如果您的 bundle 或 intent extras 太大,您可能会收到此错误。您是否将数据传递到包中?