匿名ChildEventListner Firebase Android中的内存泄漏

时间:2018-06-23 17:07:42

标签: android firebase firebase-realtime-database memory-leaks

我刚接触Android开发。我在项目中使用Firebase,在分析应用程序中,内存堆正在逐渐增加。而且我无法找到原因。我用了leakcanary库并得到了这个 screenshot from leakcanary

我有一个叫做HomeScreen的活动,其中有3个片段附加到布局上。任何人都可以帮忙吗?

HomeScreen.java

public class HomeScreen extends AppCompatActivity {

    private Toolbar toolbar;
    private TabLayout tabLayout;
    private ViewPager viewPager;
    private FloatingActionButton fab;
    CircleImageView imgView;
    AppTextView atv;
    MenuAdapter menuAdapter;
    SharedPreferences prefs;
    Button b;
    String UID;
    File file;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home_screen);

        toolbar   = findViewById(R.id.home_screen_toolbar);
        tabLayout = findViewById(R.id.home_screen_tabs);
        viewPager = findViewById(R.id.viewpager);
        fab       = findViewById(R.id.fab_home_screen);
        setSupportActionBar(toolbar);
        setupViewPager(viewPager);
        tabLayout.setupWithViewPager(viewPager);
        tabLayout.getTabAt(2).setIcon(R.drawable.peoples);
        tabLayout.getTabAt(1).setIcon(R.drawable.automated_messages);
        tabLayout.getTabAt(0).setIcon(R.drawable.ic_warning);
        prefs = getSharedPreferences(getString(R.string.USER_DATA), MODE_PRIVATE);
        UID   = prefs.getString("uid", "error");
        file  = new File(getFilesDir(), "profile");
        toolbar.setTitle("Chats");

        tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                if(tab.getPosition() == 0){
                    fab.setImageResource(R.drawable.automated_messages);
                    toolbar.setTitle("Story");
                }
                else if(tab.getPosition() == 1){
                    fab.setImageResource(R.drawable.create);
                    toolbar.setTitle("Chats");
                }
                else if(tab.getPosition() == 2){
                    fab.setImageResource(R.drawable.search);
                    toolbar.setTitle("Friends");
                }
                else
                    fab.setImageResource(android.R.color.transparent);

            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(viewPager.getCurrentItem() == 0)
                    Snackbar.make(view,"new chat",Snackbar.LENGTH_LONG).show();
                else if(viewPager.getCurrentItem() == 1)
                    createStory(view);
                else if(viewPager.getCurrentItem() == 2)
                    Snackbar.make(view,"Search friends",Snackbar.LENGTH_LONG).show();
                else
                    Snackbar.make(view,"Do nothing",Snackbar.LENGTH_SHORT).show();
            }
        });
        DuoMenuView duoMenuView = findViewById(R.id.menu);
        ArrayList<String> list = new ArrayList<>();
        list.add("Home");
        list.add("Profile");
        list.add("Friends");
        list.add("Settings");
        list.add("info");
        menuAdapter = new MenuAdapter(list);
        duoMenuView.setAdapter(menuAdapter);
        imgView = duoMenuView.getHeaderView().findViewById(R.id.dp_ico);
        b       = duoMenuView.getFooterView().findViewById(R.id.logout);
        atv     = duoMenuView.getHeaderView().findViewById(R.id.name_h);
        atv.setText(prefs.getString("name","Me"));
        if(!file.exists())
        {
            int i = R.drawable.profile;
            switch (prefs.getInt("icon",0)) {
                case 0:
                    i = R.drawable.boy_i;
                    break;
                case 1:
                    i = R.drawable.girl_i;
                    break;
                case 2:
                    i = R.drawable.boy_ii;
                    break;
                case 3:
                    i = R.drawable.girl_ii;
                    break;
                case 4:
                    i = R.drawable.boy_iii;
                    break;
                case 5:
                    i = R.drawable.girl_iii;
            }
            imgView.setImageResource(i);
        }
        else
        {
            imgView.setImageURI(Uri.fromFile(file));
        }
        final DuoDrawerLayout drawerLayout = findViewById(R.id.drawer);
        DuoDrawerToggle drawerToggle = new DuoDrawerToggle(this, drawerLayout, toolbar,
                R.string.navigation_drawer_open,
                R.string.navigation_drawer_close);

        drawerLayout.setDrawerListener(drawerToggle);
        drawerToggle.syncState();
        duoMenuView.setOnMenuClickListener(new DuoMenuView.OnMenuClickListener() {
            @Override
            public void onFooterClicked() {
                // If the footer view contains a button
                // it will launch this method on the button click.
                // If the view does not contain a button it will listen
                // to the root view click.
            }

            @Override
            public void onHeaderClicked() {

            }

            @Override
            public void onOptionClicked(int position, Object objectClicked) {
                // Set the toolbar title

                menuAdapter.setViewSelected(position, true);
                if(position == 0)//Home
                    drawerLayout.closeDrawer();
                else if(position == 1){//Profile
                    startActivity(new Intent(HomeScreen.this,Edit_Profile.class));
                }
                else if(position == 2){//Friends
                    drawerLayout.closeDrawer();
                    tabLayout.getTabAt(2).select();
                }
                else if(position == 3) {//Settings

                }
                else if(position == 4) {//Info

                }


            }
        });
        b.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AlertDialog.Builder builder = new AlertDialog.Builder(HomeScreen.this);
                builder.setTitle("Sign out?")
                        .setMessage("Do you want to sign out?\nYour personal messages will be deleted," +
                                " however your story and profile data will be saved unless you do not delete your account\nThis action cant be undone!")
                        .setPositiveButton("Sign-out", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                logout();
                            }
                        })
                        .setNeutralButton("Cancel", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                            }
                        })
                        .create();
                builder.show();
            }
        });

        drawerLayout.openDrawer();

    }
    private void setupViewPager(ViewPager viewPager) {
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        adapter.addFragment(new fragment_story_list());
        adapter.addFragment(new fragment_chat());
        adapter.addFragment(new fragment_friends());
        viewPager.setAdapter(adapter);
    }
    public void createStory(View view) {
        startActivity(new Intent(this, CreateStory.class));
        finish();
    }

    public void logout() {
        File sharedPrefFiles = new File ("/data/data/"+getPackageName()+"/shared_prefs");
        File[] FileList = sharedPrefFiles.listFiles();
        for(File file: FileList) {
            file.delete();
        }
        FirebaseAuth.getInstance().signOut();
        GoogleSignIn.getClient(HomeScreen.this,new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestIdToken(getString(R.string.default_web_client_id))
                .requestEmail()
                .build()).signOut();
        Intent i = new Intent(HomeScreen.this, SplashScreenActivity.class);
        startActivity(i);
        finish();
    }

    class ViewPagerAdapter extends FragmentPagerAdapter {
        private final List<Fragment> mFragmentList = new ArrayList<>();

        ViewPagerAdapter(FragmentManager manager) {
            super(manager);
        }

        @Override
        public Fragment getItem(int position) {
            return mFragmentList.get(position);
        }

        @Override
        public int getCount() {
            return mFragmentList.size();
        }

        void addFragment(Fragment fragment) {
            mFragmentList.add(fragment);
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return "";
        }
    }
    private Bitmap StringToBitMap(String encodedString) {
        try {
            byte[] encodeByte = Base64.decode(encodedString, Base64.DEFAULT);
            return BitmapFactory.decodeByteArray(encodeByte, 0, encodeByte.length);
        } catch (Exception e) {
            e.getMessage();
            return null;
        }
    }
    public void onDestroy() {
        super.onDestroy();
    }

    public String getUID() {
        return this.UID;
    }
}

fragment_chat.java

public class fragment_chat extends Fragment {

    ArrayList<Chats_class> chatList;
    RecyclerView chatList_rv;
    LinearLayoutManager layoutManager;
    RecyclerView.Adapter adapter;
    DatabaseReference databaseRef, rootRef;
    StorageReference storageReference;
    SharedPreferences prefs_database;
    ChildEventListener childEventListener;
    File file;

    public fragment_chat() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        prefs_database   = Objects.requireNonNull(getContext()).getSharedPreferences(getString(R.string.USER_CHAT_DATA), MODE_PRIVATE);
        chatList         = getList();
        rootRef          = FirebaseDatabase.getInstance().getReference();
        databaseRef      = rootRef.child("CHAT_LISTS").child(((HomeScreen)this.getActivity()).getUID());
        storageReference = FirebaseStorage.getInstance().getReference().child("USERS");
        file             = getContext().getFilesDir();
        childEventListener = new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                execute(dataSnapshot);
            }

            @Override
            public void onChildChanged(DataSnapshot dataSnapshot, String s) {
                execute(dataSnapshot);
            }

            @Override
            public void onChildRemoved(DataSnapshot dataSnapshot) {

            }

            @Override
            public void onChildMoved(DataSnapshot dataSnapshot, String s) {

            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
            void execute(DataSnapshot dataSnapshot)
            {
                String info = dataSnapshot.getValue(String.class);
                assert info != null;
                String last_c = info.substring(info.indexOf("#") + 1);
                int time;
                try {
                    time = Integer.parseInt(info.substring(0, info.indexOf("#") - 1));
                } catch (Exception ignore) {
                    time = 0;
                }
                getUserInfo_andSaveItToArrayList(dataSnapshot.getKey(), last_c, time);
            }
        };
        databaseRef.addChildEventListener(childEventListener);
    }

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

    }

    @Override
    public View onCreateView(
            @NonNull LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState ) {
        // Inflate the layout for this fragment
        View view       = inflater.inflate(R.layout.fragment_chat_home, container, false);
        chatList_rv     = view.findViewById(R.id.chat_list);
        adapter          = new Chat_Messages_Adapter(chatList, ((HomeScreen) Objects.requireNonNull(this.getActivity())).UID, Objects.requireNonNull(getContext()));
        layoutManager   = new LinearLayoutManager(this.getActivity());
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        chatList_rv.setLayoutManager(layoutManager);
        chatList_rv.setAdapter(adapter);
        return view;
    }

    private ArrayList<Chats_class> getList() {
        Gson gson = new Gson();
        ArrayList<Chats_class> productFromShared;
        String jsonPreferences = prefs_database.getString(getString(R.string.USER_CHAT_HISTORY_ARRAY_LIST), "");

        Type type = new TypeToken<ArrayList<Chats_class>>() {
        }.getType();
        productFromShared = gson.fromJson(jsonPreferences, type);

        if (productFromShared == null) {
            Toast.makeText(getContext(), "NO CHATS", Toast.LENGTH_LONG).show();
            return new ArrayList<>();
        }
        return productFromShared;
    }

    //public static String BitMapToString(Bitmap bitmap) {
    //    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    //    bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
    //    byte[] b = baos.toByteArray();
    //    return Base64.encodeToString(b, Base64.DEFAULT);
    //}


    void getUserInfo_andSaveItToArrayList(final String uid, final String lastMsg, final int time) {
        rootRef.child("USERS").child(uid).addListenerForSingleValueEvent(new ValueEventListener() {

            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                final UserData ud = dataSnapshot.getValue(UserData.class);
                assert ud != null;
                final Chats_class c = new Chats_class(ud.getIconID(), ud.getHasPic(), ud.getName(), lastMsg, uid, time);

                if (ud.getHasPic() > 0) {
                    if(prefs_database.getLong(uid + "_profile_Last_Seen", 0) < ud.getHasPic()) {
                        c.setProfile(0);
                        sync_database(c);
                        c.setProfile(ud.getHasPic());
                        storageReference.child(uid).child("profile.jpg").getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
                            @Override
                            public void onSuccess(final Uri uri) {

                                    Glide.with(getContext()).load(uri.toString()).asBitmap().override(80,80).into(new SimpleTarget<Bitmap>() {
                                        @Override
                                        public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
                                            // you can do something with loaded bitmap here
                                            SharedPreferences.Editor editor = prefs_database.edit();
                                            FileOutputStream fos;
                                            try {
                                                fos = getContext().openFileOutput(uid+"_profile", MODE_PRIVATE);
                                                resource.compress(Bitmap.CompressFormat.JPEG, 90, fos);
                                                fos.close();
                                            } catch (IOException e) {
                                                e.printStackTrace();
                                            }
                                            editor.putLong(uid + "_profile_Last_Seen", ud.getHasPic());
                                            editor.apply();
                                            sync_database(c);
                                        }
                                    });
                                }
                        });
                    }
                    else
                        sync_database(c);
                }
                else if (ud.getHasPic() <= 0) {
                    SharedPreferences.Editor editor = prefs_database.edit();
                    editor.remove(uid + "_profile");
                    editor.apply();
                    sync_database(c);
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });

    }

    void sync_database(Chats_class chats) {
        if(chatList.isEmpty()) {
            chatList.add(chats);
            adapter.notifyDataSetChanged();
        }
        else {
            boolean found = false;
            for (int i = 0; i < chatList.size(); i++) {
                if (chatList.get(i).getUid().equals(chats.getUid())) {
                    if (!chatList.get(i).equals(chats)) {
                        chatList.set(i, chats);
                        adapter.notifyItemChanged(i);
                    }
                    found = true;
                    break;
                }
            }
            if (!found) {
                chatList.add(chats);
                adapter.notifyItemInserted(chatList.size() - 1);
            }
        }
    }

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

    @Override
    public void onStop() {
        super.onStop();
        Application_Class.getRefWatcher((this.getActivity())).watch(this);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        databaseRef.removeEventListener(childEventListener);
        childEventListener = null;
        SharedPreferences.Editor prefsEditor = prefs_database.edit();
        Gson gson = new Gson();
        String json = gson.toJson(chatList);
        prefsEditor.putString(getString(R.string.USER_CHAT_HISTORY_ARRAY_LIST), json);
        prefsEditor.apply();
    }
}

0 个答案:

没有答案