below is my leak report captured by leak canary but i am not able to detect from where it keeps referencing object
* GC ROOT maps.O.n.d
* references maps.ae.e.i
* references java.util.ArrayList.array
* references array java.lang.Object[].[15]
* references maps.af.a$2.b
* references maps.af.a.c
* references maps.af.b.c
* references maps.af.d.mParent
* references android.widget.FrameLayout.mParent
* references com.google.android.gms.maps.MapView.mParent
* references android.widget.LinearLayout.mParent
* references android.support.v7.widget.CardView.mParent
* references android.widget.LinearLayout.mLayoutParams
* references android.support.v7.widget.RecyclerView$LayoutParams.mViewHolder
* references com.aimdek.healthwel.adapter.FeedsAdpter$MyViewHolder.this$0
* references com.aimdek.healthwel.adapter.FeedsAdpter.feedsFragment
* leaks com.aimdek.healthwel.fragment.FeedsFragment instance
* Retaining: 1.0 KB.
* Reference Key: f46244a8-7376-452a-969b-6f19fd070ea2
* Device: motorola motorola XT1068 titan_retaildsds
* Android Version: 6.0 API: 23 LeakCanary: 1.4-beta2 3799172
* Durations: watch=5202ms, gc=259ms, heap dump=13581ms, analysis=108725ms
* Details:
* Instance of maps.O.n
| static f = java.util.Arrays$ArrayList@315426320 (0x12cd0610)
| static $staticOverhead = byte[8]@328672257 (0x13972401)
| g = -1
| f = false
| g = 256
| h = java.util.Arrays$ArrayList@315426320 (0x12cd0610)
| i = 0
| j = 1
| k = 2.0
| b = maps.O.k@322255648 (0x13353b20)
| c = maps.M.ac$i@316399200 (0x12dbde60)
| d = maps.ae.e@332202880 (0x13cd0380)
| f = null
| g = java.util.concurrent.locks.ReentrantLock@315427056 (0x12cd08f0)
| h = maps.y.m@328083040 (0x138e2660)
| i = maps.O.b$3@316588288 (0x12dec100)
| j = false
| k = maps.O.n$1@315570880 (0x12cf3ac0)
| l = java.util.LinkedList@316435840 (0x12dc6d80)
| m = maps.O.b$2@316435936 (0x12dc6de0)
| n = java.util.HashMap@322255600 (0x13353af0)
| o = 3000
| p = 0
| q = 0
| r = 0
| s = false
| t = java.util.ArrayList@316435904 (0x12dc6dc0)
| u = false
| v = maps.O.b$1@315427072 (0x12cd0900)
| contextClassLoader = dalvik.system.PathClassLoader@315133024 (0x12c88c60)
| daemon = false
| group = java.lang.ThreadGroup@1869718984 (0x6f71a5c8)
| hasBeenStarted = true
| id = 9069
| inheritableValues = null
| interruptActions = java.util.ArrayList@316435584 (0x12dc6c80)
| localValues = java.lang.ThreadLocal$Values@316588192 (0x12dec0a0)
| lock = java.lang.Object@315427040 (0x12cd08e0)
| name = java.lang.String@322255456 (0x13353a60)
| nativePeer = -1194656976
| parkBlocker = null
| parkState = 1
| priority = 5
| stackSize = 0
| target = null
| uncaughtHandler = null
| shadow$_klass_ = maps.O.n
| shadow$_monitor_ = 1267345999
* Instance of maps.ae.e
| static $staticOverhead = byte[24]@331324817 (0x13bf9d91)
| static j = java.lang.String@332151648 (0x13cc3b60)
| static s = java.util.HashMap@332198576 (0x13ccf2b0)
| static a =
| mParentFragment = FriendFragment@317174144 (0x12e7b180)
| mReenterTransition = java.lang.Object@326447456 (0x13753160)
| mRemoving = false
| mRestored = false
| mRetainInstance = false
| mRetaining = false
| mReturnTransition = java.lang.Object@326447456 (0x13753160)
| mSavedFragmentState = null
| mSavedViewState = android.util.SparseArray@324672992 (0x135a1de0)
| mSharedElementEnterTransition = null
| mSharedElementReturnTransition = java.lang.Object@326447456 (0x13753160)
| mState = 0
| mStateAfterAnimating = 0
| mTag = null
| mTarget = null
| mTargetIndex = -1
| mTargetRequestCode = 0
| mUserVisibleHint = false
| mView = null
| mWho = null
| shadow$_klass_ = com.aimdek.healthwel.fragment.FeedsFragment
| shadow$_monitor_ = -2095684492
* Excluded Refs:
| Field: android.view.inputmethod.InputMethodManager.mNextServedView
| Field: android.view.inputmethod.InputMethodManager.mServedView
| Field: android.view.inputmethod.InputMethodManager.mServedInputConnection
| Field: android.view.inputmethod.InputMethodManager.mCurRootView
| Field: android.widget.Editor$Blink.this$0
| Field: android.view.Choreographer$FrameDisplayEventReceiver.mMessageQueue (always)
Instance of com.aimdek.healthwel.adapter.FeedsAdpter
| allFeedsList = java.util.ArrayList@326789152 (0x137a6820)
| context = com.aimdek.healthwel.activity.MainActivity@315004672 (0x12c69700)
| feedsFragment = com.aimdek.healthwel.fragment.FeedsFragment@315395840 (0x12cc8f00)
| inflater = com.android.internal.policy.PhoneLayoutInflater@322687328 (0x133bd160)
| mHasStableIds = false
| mObservable = android.support.v7.widget.RecyclerView$AdapterDataObservable@316485552 (0x12dd2fb0)
| shadow$_klass_ = com.aimdek.healthwel.adapter.FeedsAdpter
| shadow$_monitor_ = 0
* Instance of com.aimdek.healthwel.fragment.FeedsFragment
| adapter = com.aimdek.healthwel.adapter.FeedsAdpter@321038624 (0x1322a920)
| birthday = android.support.v7.widget.AppCompatTextView@332811264 (0x13d64c00)
| dateformat = java.text.SimpleDateFormat@320969344 (0x13219a80)
| email = android.support.v7.widget.AppCompatTextView@332332032 (0x13cefc00)
| feedsId = null
| friendImg = com.mikhaellopez.circularimageview.CircularImageView@332806144 (0x13d63800)
| friendInfo = null
| imgBackground = android.widget.LinearLayout@332061696 (0x13cadc00)
| imgFriendBackground = android.support.v7.widget.AppCompatImageView@329300992 (0x13a0bc00)
| page = 1
| profile = android.widget.LinearLayout@332058624 (0x13cad000)
| recyclerView = com.malinskiy.superrecyclerview.SuperRecyclerView@332813312 (0x13d65400)
| secondLevel = false
| tvBirthDate = android.support.v7.widget.AppCompatTextView@332812288 (0x13d65000)
| tvEmailId = android.support.v7.widget.AppCompatTextView@332335104 (0x13cf0800)
| tvHeight = android.support.v7.widget.AppCompatTextView@332810240 (0x13d64800)
| tvName = android.support.v7.widget.AppCompatTextView@332807168 (0x13d63c00)
| tvWeight = android.support.v7.widget.AppCompatTextView@332326912 (0x13cee800)
| type = 21
| userId = java.lang.String@314601152 (0x12c06ec0)
| activity = com.aimdek.healthwel.activity.MainActivity@315004672 (0x12c69700)
| mAdded = false
| mAllowEnterTransitionOverlap = null
| mAllowReturnTransitionOverlap = null
| mAnimatingAway = null
| mArguments = android.os.Bundle@320969440 (0x13219ae0)
| mBackStackNesting = 0
| mCalled = true
| mCheckedForLoaderManager = false
| mChildFragmentManager = null
| mContainer = null
| mContainerId = 0
| mDeferStart = false
| mDetached = false
| mEnterTransition = null
| mEnterTransitionCallback = null
| mExitTransition = null
| mExitTransitionCallback = null
| mFragmentId = 0
| mFragmentManager = null
| mFromLayout = false
| mHasMenu = true
| mHidden = false
| mHost = null
| mInLayout = false
| mIndex = -1
| mInnerView = null
| mLoaderManager = null
| mLoadersStarted = false
| mMenuVisible = false
| mNextAnim = 0
| mParentFragment = com.aimdek.healthwel.fragment.FriendFragment@317174144 (0x12e7b180)
| mReenterTransition = java.lang.Object@326447456 (0x13753160)
| mRemoving = false
| mRestored = false
| mRetainInstance = false
| mRetaining = false
| mReturnTransition = java.lang.Object@326447456 (0x13753160)
| mSavedFragmentState = null
| mSavedViewState = android.util.SparseArray@324672992 (0x135a1de0)
| mSharedElementEnterTransition = null
| mSharedElementReturnTransition = java.lang.Object@326447456 (0x13753160)
| mState = 0
| mStateAfterAnimating = 0
| mTag = null
| mTarget = null
| mTargetIndex = -1
| mTargetRequestCode = 0
| mUserVisibleHint = false
| mView = null
| mWho = null
| shadow$_klass_ = com.aimdek.healthwel.fragment.FeedsFragment
| shadow$_monitor_ = -2095684492
below is code for FeedsAdapter
public class FeedsAdpter extends RecyclerView.Adapter<FeedsAdpter.MyViewHolder> {
private LayoutInflater inflater;
private Context context;
private FeedsFragment feedsFragment;
private ArrayList<FeedsDto> allFeedsList = new ArrayList<FeedsDto>();
public FeedsAdpter(Context context, FeedsFragment feedsFragment) {
this.context = context;
this.feedsFragment = feedsFragment;
inflater = LayoutInflater.from(context);
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.item_feeds, parent, false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
@Override
public void onViewRecycled(MyViewHolder holder) {
super.onViewRecycled(holder);
if(Validator.isNotNull(holder.mapView.getMap())) {
GoogleMap googleMap = holder.mapView.getMap();
googleMap.clear();
googleMap.setMapType(GoogleMap.MAP_TYPE_NONE);
googleMap=null;
}
}
@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
final FeedsDto feeds = allFeedsList.get(position);
GoogleMap googleMap;
if (Validator.isNotNull(feeds)) {
if (Validator.isNotNull(feeds.getImagePreviewUrl())) {
//imageLoader.displayImage(feeds.getImagePreviewUrl(), holder.userImg, HWUtil.IMAGE_OPTIONS);
Picasso.with(context).setIndicatorsEnabled(true);
Picasso.with(context)
.load(feeds.getImagePreviewUrl())
.resize(50,50)
.onlyScaleDown()
.placeholder(R.drawable.ic_launcher)
.error(R.drawable.profile_small_img)
.into(holder.userImg);
} else {
holder.userImg.setImageResource(R.drawable.profile_small_img);
}
holder.tvUserName.setText(feeds.getFullName());
MainActivity activity = (MainActivity) context;
String tempMsg = feeds.getFeeds().getMessage();
if (Validator.isNotNull(feeds.getFeeds().getHistoryId())) {
if (feeds.getFeeds().getUserId().equals(activity.preferences.getUserInfo().getId())) {
tempMsg = tempMsg.replace("[$ACTIVITY_OWNER$]", activity.getResources().getString(R.string.was_out));
} else {
tempMsg = tempMsg.replace("[$ACTIVITY_OWNER$]", activity.getResources().getString(R.string.was_out));
}
} else {
tempMsg = tempMsg.replace("[$ACTIVITY_OWNER$]", "");
}
holder.tvMsg.setText(tempMsg);
if (feeds.isLiked()) {
holder.likeBtn.setImageResource(R.drawable.like_icon_pink);
} else {
holder.likeBtn.setImageResource(R.drawable.like_icon_grey);
}
holder.tvDuration.setText(feeds.getFeedCreatedTime());
if (Validator.isNotNull(feeds.getFeeds().getHistoryMap()) && feeds.getFeeds().getHistoryMap().length > 0) {
if (holder.mapView != null) {
holder.mapView.onCreate(null);
holder.mapView.setVisibility(View.VISIBLE);
holder.mapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(GoogleMap googleMap) {
if (Validator.isNotNull(googleMap)) {
googleMap.clear();
holder.mapView.setClickable(false);
googleMap.getUiSettings().setMapToolbarEnabled(false);
List<HistoryMap> historyMaps = new ArrayList<HistoryMap>();
historyMaps.addAll(Arrays.asList(feeds.getFeeds().getHistoryMap()));
HWUtil.drawRouteIntoMap(historyMaps, googleMap);
}
}
});
}
} else {
holder.mapView.setVisibility(View.GONE);
}
holder.tvCommentcount.setText(String.valueOf(feeds.getFeeds().getCommentCount()));
if (feeds.getFeeds().getCommentCount() == 0) {
holder.commentBtn.setImageResource(R.drawable.comment_icon_grey_feeds);
} else {
holder.commentBtn.setImageResource(R.drawable.comment_icon_feeds);
}
holder.tvLikecount.setText(String.valueOf(feeds.getFeeds().getLikeCount()));
holder.tvPost.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (Validator.isNotNull(holder.etComment.getText().toString())) {
hideKeyboard(context);
String comment = holder.etComment.getText().toString();
feedsFragment.updateComment(feeds.getFeeds().getId(), comment);
holder.etComment.setText(HWUtil.BLANK);
} else {
HWUtil.showToast(context, context.getResources().getString(R.string.enter_comment));
}
}
});
holder.likeBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
feedsFragment.updateComment(feeds.getFeeds().getId(), null);
}
});
holder.commentBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MainActivity activity = (MainActivity) context;
activity.setTitle(context.getString(R.string.comment));
activity.preferences.setBack(true);
activity.preferences.setFeedsDto(feeds);
activity.replaceFragment(new CommentFragment(), null);
}
});
}
}
public static void hideKeyboard(Context context) {
try {
InputMethodManager inputManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
View view = ((Activity) context).getCurrentFocus();
if (view != null) {
inputManager.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void addAll(List<FeedsDto> list) {
allFeedsList.addAll(list);
notifyDataSetChanged();
}
public void clear() {
allFeedsList = new ArrayList<FeedsDto>();
notifyDataSetChanged();
}
@Override
public int getItemCount() {
return allFeedsList.size();
}
public void updateFeeds(String feedsId, com.aimdek.healthwel.dto.Response response, int type) {
FeedsDto dto = getFeedsDto(feedsId);
if (Validator.isNotNull(dto)) {
if (type == Request.LIKE_UNLIKE) {
dto.getFeeds().setLikeCount(response.getCount());
dto.setLiked(response.isLiked());
} else {
dto.getFeeds().setCommentCount(response.getCount());
}
}
notifyDataSetChanged();
}
public FeedsDto getFeedsDto(String feedsId) {
for (FeedsDto dto : allFeedsList) {
if (dto.getFeeds().getId().equals(feedsId)) {
return dto;
}
}
return null;
}
public class MyViewHolder extends RecyclerView.ViewHolder {
@Bind(R.id.img_user_pic)
ImageView userImg;
@Bind(R.id.tv_user_name)
TextView tvUserName;
@Bind(R.id.tv_duration)
TextView tvDuration;
@Bind(R.id.tv_msg)
TextView tvMsg;
@Bind(R.id.workout_map_summary)
MapView mapView;
@Bind(R.id.et_feeds_comment)
EditText etComment;
@Bind(R.id.tv_post)
TextView tvPost;
@Bind(R.id.img_like_btn)
ImageButton likeBtn;
@Bind(R.id.img_comment_btn)
ImageButton commentBtn;
@Bind(R.id.tv_like_count)
TextView tvLikecount;
@Bind(R.id.tv_comment_count)
TextView tvCommentcount;
public MyViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
}
}
}
as user likes or comment on particular feeds i invoke fragment class method to update this and i m showing feeds of friend in app.which will create leak when i m showing feeds of individual friend any idea on how to fix this.any help is appriciated
you should release mNextServedView when the focused window is dismissed(such as onStop or onDestory).
code like :
InputMethodManager methodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
try {
Field mNextServedView = methodManager.getClass().getDeclaredField("mNextServedView");
mNextServedView.setAccessible(true);
mNextServedView.set(methodManager, null);
Field mServedView = methodManager.getClass().getDeclaredField("mServedView");
mServedView.setAccessible(true);
mServedView.set(methodManager, null);
Method method = methodManager.getClass().getDeclaredMethod("finishInputLocked");
method.setAccessible(true);
method.invoke(methodManager);
} catch (Throwable e) {
e.printStackTrace();
}