How to find memory leaks using LeakCanary in the Android app? - android

Help please find memory leaks in my app.
LeakCanary:
-static android.app.ActivityThread.sCurrentActivityThread
-references android.utill.ArrayMap.mArray
-reference array java.lang.Object[].1
-references android.app.ActivityThread$ActivityClientRecord.activity
-references MainActivity.tf (tf - my fragment)
-leaks TheaterFragment instance
Example code fragment:
public class TheaterFragment extends Fragment {
Typeface face;
private View view;
private RelativeLayout rl;
private LinearLayout linearLayout;
private int wordLheigh, screenWidht, wordLength, margin, btnHeight;
private String word;
private float scale;
private Animation anim;
private int tangelSound, whooshSound;
private SoundPool mSoundPool2;
private int soundMusic;
private boolean startAnim = false;
private LayoutAnimationController controller;
#Override
public void onStart(){
super.onStart();
if (!word.equals("suoh") && startAnim) {
anim = AnimationUtils.loadAnimation(getActivity(), R.anim.theater);
anim.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
mSoundPool2.play(whooshSound, soundMusic, soundMusic, 0, 0, 1);
rl.setClickable(false);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
// linearLayout.startLayoutAnimation();
startAnim = false;
Animation anim1 = AnimationUtils.loadAnimation(getActivity(), R.anim.blueword);
anim1.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
mSoundPool2.play(tangelSound, soundMusic, soundMusic, 0, wordLength, 0.5f);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
// rl.setClickable(true);
}
});
controller = new LayoutAnimationController(anim1, 0.5f);
linearLayout.setLayoutAnimation(controller);
linearLayout.setLayoutAnimationListener(new Animation.AnimationListener() {
public void onAnimationEnd(Animation _animation) {
rl.setClickable(true);
}
public void onAnimationRepeat(Animation _animation) {
}
public void onAnimationStart(Animation _animation) {
}
});
linearLayout.setVisibility(View.VISIBLE);
linearLayout.startLayoutAnimation();
}
});
rl.setVisibility(View.VISIBLE);
rl.startAnimation(anim);
}
}
public void falseClickable(){
rl.setClickable(false);
rl.setEnabled(false);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
face = Typefaces.get(getContext(), getContext().getText(R.string.font_droidsans).toString());
if (Build.VERSION.SDK_INT >= 21)
{
AudioAttributes attributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
mSoundPool2 = new SoundPool.Builder()
.setAudioAttributes(attributes)
.build();
} else {
mSoundPool2 = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);
}
tangelSound = mSoundPool2.load(getActivity(), R.raw.tangel, 1);
whooshSound = mSoundPool2.load(getActivity(), R.raw.whoosh3, 1);
scale = getArguments().getInt("scale");
wordLheigh = getArguments().getInt("wordLheigh");
screenWidht = getArguments().getInt("screenWidht");
word = getArguments().getString("word");
wordLength = word.length();
soundMusic = getArguments().getInt("soundMusic");
startAnim = getArguments().getBoolean("startAnim");
//Log.e("TylyTaay", Integer.toString(FINAL));
margin = (int) (getResources().getDimension(R.dimen.word_btn_margin)+0.5f);
btnHeight = (int) (screenWidht / 10 - 4 * margin +0.5f);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_theater, container, false);
rl = (RelativeLayout) view.findViewById(R.id.theaterLayout);
TextView tv1 = (TextView) view.findViewById(R.id.textView1);
TextView tv2 = (TextView) view.findViewById(R.id.textView1);
tv1.setTypeface(face);
tv2.setTypeface(face);
if (!word.equals("suoh")){
linearLayout = (LinearLayout) view.findViewById(R.id.clonWordLayout);
RelativeLayout.LayoutParams lparams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, wordLheigh);
lparams.setMargins(0, screenWidht, 0, 0);
linearLayout.setLayoutParams(lparams);
setClon();
} else {
rl.setVisibility(View.VISIBLE);
}
return view;
}
#Override
public void onDestroy() {
super.onDestroy();
linearLayout.removeAllViews();
linearLayout = null;
RefWatcher refWatcher = MyApp.getRefWatcher(getActivity());
refWatcher.watch(this);
}
private void setClon()
{
Button btn;
for(int i = 0; i < wordLength; i++)
{
btn = new Button(getActivity());
char[] ch = {word.charAt(i)};
String st = new String(ch);
btn.setText(st);
btn.setGravity(Gravity.CENTER);
btn.setPadding(0, 0, 0, 0);
btn.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(R.dimen.word_btn_text_size));
btn.setBackgroundResource(R.drawable.btn_word_win);
btn.setTextColor(getResources().getColorStateList(R.color.dark_gray));
btn.setClickable(false);
btn.setTypeface(face);
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(btnHeight, btnHeight);
lparams.setMargins(margin, 0,margin, 0);
linearLayout.addView(btn, lparams); //Добавляем в LinearLayout
}
btn = null;
}
public void playSound(int nameSound ) {
if (soundMusic == 1)
mSoundPool2.play(nameSound,1,1,0,0,1);}
The sample code in MainActivity, which call the fragment:
private void rightAnswer()
{
if (imgZoom != null) {
imgZoomBack(wordL);
}
wordL.blockWord(false);
buttonL.blockBtn(false);
gridView.setOnItemClickListener(null);
//tf = new TheaterFragment(scale, wordLheigh, screenWidht, word, bar.tvDiamond, bar.tvLevel, bar.imageView, wordId);
if (tf == null) {
tf = new TheaterFragment();
}
if (args == null) {
args = new Bundle();
}
args.putFloat("scale", scale);
args.putInt("wordLheigh", wordLheight);
args.putInt("screenWidht", screenWidht);
args.putInt("soundMusic", soundOnOff);
args.putBoolean("startAnim", true);
args.putString("word", word);
//Log.e("TylyTaay", Integer.toString(wordId));
args.putInt("wordId", wordId);
tf.setArguments(args);
args = null;
getSupportFragmentManager()
.beginTransaction()
.add(R.id.frameLayout, tf)
.commit();
YoYo.with(Techniques.SlideOutDown)
.playOn(bar.tgDiamond);
YoYo.with(Techniques.SlideOutDown)
.playOn(bar.tgVolume);
YoYo.with(Techniques.SlideOutDown)
.playOn(bar.tvDiamond);
YoYo.with(Techniques.SlideOutDown)
.playOn(bar.tvLevel);
bar.imageView.setVisibility(View.VISIBLE);
YoYo.with(Techniques.SlideInDown)
.playOn(bar.imageView);}

I'm late for the response, this might be helpful for others.
As mentioned by #tsiro LeakCanary has its own bugs, you can go here for more details.
For your code,
getSupportFragmentManager()
.beginTransaction()
.add(R.id.frameLayout, tf)
.commit();
Here you are adding the fragment in FragmentManager but you are not removing it when the activity goes to background or when the fragment is changed/reinitialised.
Try removing the fragment from the fragment manager, if you are using .add().
You can use .replace() which calls .remove() and .add() implicitly.
I hope it helps.

i have just noticed that i take the same output in my application.Even though i double checked my app for possible memory leaks and after i resolve the actual point in my code where memory leak occured, i am still getting this message...you do not have to worry about it, probably it is a bug created by LeakCanary library...just ignore it as i did..

Related

Recycler View add Item Animator not animating

I am trying to use a custom Item Animator for animating an itemview after clicking a button. After clicking the add button, the new item appear, but the desired animation does not happen. It just appears suddenly. I have tried everything, please help.
viewholder_add_anim
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:duration = "500"
android:fromXScale="0%"
android:fromYScale="0%"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="100%"
android:toYScale="100%"/>
</set>
CustomItemAnimator
import android.view.animation.AnimationUtils;
import com.example.bookui.R;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.RecyclerView;
public class CustomItemAnimator extends DefaultItemAnimator {
#Override
public boolean animateRemove(RecyclerView.ViewHolder holder) {
return super.animateRemove(holder);
}
#Override
public boolean animateAdd(RecyclerView.ViewHolder holder) {
holder.itemView.setAnimation(AnimationUtils.loadAnimation(holder.itemView.getContext(),
R.anim.viewholder_add_anim));
return super.animateAdd(holder);
}
}
Main Activity
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerViewBooks;
private BookAdapter bookAdapter;
private List<Book> mdata;
private Button addButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
initmdataBooks();
setUpBookAdapter();
}
private void initViews() {
addButton = findViewById(R.id.add_btn);
recyclerViewBooks = findViewById(R.id.recyclerView);
recyclerViewBooks.setHasFixedSize(true);
recyclerViewBooks.setItemAnimator(new CustomItemAnimator());
addButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
addBook();
}
});
}
private void initmdataBooks() {
mdata = new ArrayList<>();
mdata.add(new Book(R.drawable.book1));
mdata.add(new Book(R.drawable.book2));
mdata.add(new Book(R.drawable.book3));
mdata.add(new Book(R.drawable.book2));
mdata.add(new Book(R.drawable.book4));
mdata.add(new Book(R.drawable.book5));
mdata.add(new Book(R.drawable.book1));
mdata.add(new Book(R.drawable.book1));
mdata.add(new Book(R.drawable.book5));
}
private void setUpBookAdapter() {
bookAdapter = new BookAdapter(mdata);
recyclerViewBooks.setAdapter(bookAdapter);
}
private void addBook() {
Book book = new Book(R.drawable.book4);
mdata.add(1, book);
bookAdapter.notifyDataSetChanged();
}
}
You have to properly fullfill ItemAnimator contract instead of blindly overriding animateAdd:
Don't call through to super.animateAdd(holder) - you're just going to run into conflict with default fade in animation.
You have to keep track of this animation and call dispatchAddStarting(holder) / dispatchAddFinished(holder) to inform super implementation of current animation state.
You have to override few more methods (in code below) that must be aware of whether your animations are running and provide cancellation option
Sample DefaultItemAnimator overriden to run a scale up animation on newly added items:
public class AddRecAnimator extends DefaultItemAnimator {
private final static String TAG = "AddRecAnimator";
// must keep track of all pending/ongoing animations.
private final ArrayList<AddHolder> pending = new ArrayList<>();
private final HashMap<RecyclerView.ViewHolder, AddHolder> additions = new HashMap<>();
#Override
public boolean animateAdd(RecyclerView.ViewHolder holder) {
pending.add(new AddHolder(holder));
return true; // return true to receive call to runPendingAnimations
}
#Override
public void runPendingAnimations() {
for (AddHolder ah : pending) {
ah.start();
}
pending.clear();
super.runPendingAnimations();
}
#Override
public void endAnimation(RecyclerView.ViewHolder item) {
AddHolder ah = additions.get(item);
if (ah != null) {
ah.endAnimation();
}
super.endAnimation(item);
}
#Override
public void endAnimations() {
for (AddHolder ah : pending) {
ah.resetViewHolderState();
dispatchAddFinished(ah.holder);
}
for (AddHolder ah : additions.values()) {
ah.resetViewHolderState();
dispatchAddFinished(ah.holder);
}
pending.clear();
additions.clear();
super.endAnimations();
}
#Override
public boolean isRunning() {
return super.isRunning() &&
!pending.isEmpty() &&
!additions.isEmpty();
}
/**
* This is container for addition animation. It's also end listener for it.
*/
private final class AddHolder implements Animation.AnimationListener {
private final RecyclerView.ViewHolder holder;
private AddHolder(RecyclerView.ViewHolder holder) {
this.holder = holder;
Animation anim = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f,
ScaleAnimation.RELATIVE_TO_SELF, 0.5f,
ScaleAnimation.RELATIVE_TO_SELF, 0.5f);
anim.setDuration(500);
anim.setAnimationListener(this);
holder.itemView.setAnimation(anim);
dispatchAddStarting(holder);
}
void start() {
View itemView = holder.itemView;
Animation a = itemView.getAnimation();
if (a != null) {
a.start();
additions.put(holder, this);
} else {
endAnimation(); // invalid state, animation missing
}
}
private void resetViewHolderState() {
// reset state as if no animation was ran
Animation a = holder.itemView.getAnimation();
if (a != null) {
a.setAnimationListener(null);
a.cancel();
holder.itemView.clearAnimation();
}
holder.itemView.setScaleX(1f);
holder.itemView.setScaleY(1f);
}
// called when animation ends or is manually cancelled
protected void endAnimation(){
additions.remove(holder);
resetViewHolderState();
dispatchAddFinished(holder);
// if all animations in animator are done dispatch they're finished
if (!isRunning()) dispatchAnimationsFinished();
}
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
endAnimation();
}
#Override
public void onAnimationRepeat(Animation animation) {
}
}
}

Bug: Slider Appearing Every time using viewpager

i am making a slider walkthrough which is introduced in the app for the first item when the user clicks the app....and it is gone when the user again open it.
like this: https://www.youtube.com/watch?v=va2IRW_e7_w
the problem is that i am regaining it again and again whenever i opent the app, its a small mistake and i can't find it.
Main2Activity:
public class Main2Activity extends AppCompatActivity {
Button next, skip;
private ViewPagerAdapter adapter;
private ViewPager viewPager;
private SliderWalkthrough sliderWalkthrough;
private int[] layouts;
private TextView[] dots;
private LinearLayout dotsLayout;
ViewPager.OnPageChangeListener listener = new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
addButtonDots(position);
if (position == layouts.length - 1) {
next.setText("GET STARTED");
skip.setVisibility(View.GONE);
} else {
next.setText("NEXT");
skip.setVisibility(View.VISIBLE);
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sliderWalkthrough = new SliderWalkthrough(this);
if (!sliderWalkthrough.Check()) {
sliderWalkthrough.setFirst(false);
Intent intent = new Intent(Main2Activity.this, MainActivity.class);
startActivity(intent);
finish();
}
if (Build.VERSION.SDK_INT >= 21) {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
setContentView(R.layout.activity_main2);
viewPager = (ViewPager) findViewById(R.id.id_WalkThroughViewPager);
dotsLayout = (LinearLayout) findViewById(R.id.layout_dots);
layouts = new int[]{R.layout.slider_walkthrough_screen1, R.layout.slider_walkthrough_screen2, R.layout.slider_walkthrough_screen3};
addButtonDots(0);
adapter = new ViewPagerAdapter();
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(listener);
}
private void addButtonDots(int position) {
dots = new TextView[layouts.length];
int[] colorActive = getResources().getIntArray(R.array.active_dot);
int[] colorInactive = getResources().getIntArray(R.array.inactive_dot);
dotsLayout.removeAllViews();
for (int i = 0; i < dots.length; i++) {
dots[i] = new TextView(this);
dots[i].setTextSize(30);
dots[i].setTextColor(colorInactive[position]);
dotsLayout.addView(dots[i]);
}
if (dots.length > 0) {
dots[position].setTextColor(colorActive[position]);
}
}
}
SliderWalkthrough:
public class SliderWalkthrough {
SharedPreferences sharedPreferences;
SharedPreferences.Editor editor;
Context context;
public SliderWalkthrough(Context context) {
this.context = context;
sharedPreferences=context.getSharedPreferences("first",0);
editor=sharedPreferences.edit();
}
public void setFirst(Boolean firstTime){
editor.putBoolean("check",firstTime);
editor.commit();
}
public boolean Check()
{
return sharedPreferences.getBoolean("check",true);
}
}
You need to change the preference value to false once your walk-through is finished otherwise if (!sliderWalkthrough.Check()) { will never be executed and walk-through will be shown everytime
#Override
public void onPageSelected(int position) {
addButtonDots(position);
if (position == layouts.length - 1) {
next.setText("GET STARTED");
skip.setVisibility(View.GONE);
sliderWalkthrough.setFirst(false);
//^^^^^^ add this case
}
else {
next.setText("NEXT");
skip.setVisibility(View.VISIBLE);
}
}
Note : remove sliderWalkthrough.setFirst(false); , no longer required
if (!sliderWalkthrough.Check()) {
Intent intent = new Intent(Main2Activity.this, MainActivity.class);
startActivity(intent);
finish();
}

How to make 500 Questions Quiz in android with single activity?

I am creating an android app, where I'll be asking for multiple types of questions using RadioButtons. I don't want to make multiple Activities for these questions. Can anyone please tell me how to do that with a short example, of at least two questions?
You can use multiples fragments... or call the activity itself multiple times...
I did an app like yours and i choose the first method!
This is some fragment of a project that i wrote, and the activity that manipulate it, you will have to change it according to your needs.
Activity
public class CollectActivity extends FragmentActivity {
MyPageAdapter pageAdapter;
NonSwipeableViewPager pager;
SpringIndicator springIndicator;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_collect);
List<Fragment> fragments = getFragments();
pager = (NonSwipeableViewPager) findViewById(R.id.view_pager);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
PagerModelManager manager = new PagerModelManager();
manager.addCommonFragment(fragments, getTitles());
ModelPagerAdapter adapter = new ModelPagerAdapter(getSupportFragmentManager(), manager);
pager.setAdapter(adapter);
springIndicator = (SpringIndicator) findViewById(R.id.indicator);
springIndicator.setViewPager(pager);
springIndicator.setOnTabClickListener(new TabClickListener() {
#Override
public boolean onTabClick(int position) {
return false;
}
});
}
private List<Fragment> getFragments() {
List<Fragment> fList = new ArrayList<Fragment>();
fList.add(CollectFragment.newInstance("Fragment 1"));
fList.add(CollectFragment.newInstance("Fragment 2"));
fList.add(CollectFragment.newInstance("Fragment 3"));
//add your fragments with a loop
return fList;
}
private List<String> getTitles() {
return Lists.newArrayList("1", "2", "3");
}
public void swipeFragment() {
pager.setCurrentItem(pager.getCurrentItem() + 1);
}
public int getFragment() {
return pager.getCurrentItem();
}
}
Fragment
public class CollectFragment extends Fragment {
private Button openButton;
private Button confirmationCloseButton;
private Button yesRenew;
private Button noRenew;
private BroadcastReceiver udpMessages;
public static final String EXTRA_MESSAGE = "EXTRA_MESSAGE";
public static final CollectFragment newInstance(String message) {
CollectFragment f = new CollectFragment();
Bundle bdl = new Bundle(1);
bdl.putString(EXTRA_MESSAGE, message);
f.setArguments(bdl);
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String message = getArguments().getString(EXTRA_MESSAGE);
View v = null;
if (message.compareTo("Fragment 1") == 0) {
v = inflater.inflate(R.layout.fragment_collect_open, container, false);
openButton = (Button) v.findViewById(R.id.open_button);
openButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i2 = new Intent();
i2.setComponent(new ComponentName("qira.com.locker", "qira.com.locker.Service.MessageService"));
i2.putExtra("Message", "CONFIRM_LOCKER_1_CLOSED");
getContext().startService(i2);
}
});
}
if (message.compareTo("Fragment 2") == 0) {
v = inflater.inflate(R.layout.fragment_collect_close, container, false);
confirmationCloseButton = (Button) v.findViewById(R.id.confirmation_close_button);
confirmationCloseButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i2 = new Intent();
i2.setComponent(new ComponentName("qira.com.locker", "qira.com.locker.Service.MessageService"));
i2.putExtra("Message", "OPEN_LOCKER_1");
getContext().startService(i2);
}
});
}
if (message.compareTo("Fragment 3") == 0) {
v = inflater.inflate(R.layout.fragment_collect_renew, container, false);
yesRenew = (Button) v.findViewById(R.id.yes_button);
noRenew = (Button) v.findViewById(R.id.no_button);
yesRenew.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
((CollectActivity) getActivity()).swipeFragment();
}
});
noRenew.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(getContext(), ReserveActivity.class);
startActivity(i);
}
});
}
return v;
}
#Override
public void onResume() {
super.onResume();
udpMessages = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() != null && intent.getAction().equals("UDP.MESSAGES.COLLECT")) {
if (intent.getExtras().getString("Type").compareTo("OPEN_LOCKER_1-LOCKER_OPENED") == 0) {
if (((CollectActivity) getActivity()).getFragment() != 0) { // onCreateView called twice, dont know why... workaround to solve this problem
((CollectActivity) getActivity()).swipeFragment();
}
}
if (intent.getExtras().getString("Type").compareTo("CONFIRM_LOCKER_1_CLOSED-TRUE") == 0) {
if (((CollectActivity) getActivity()).getFragment() != 1) { // onCreateView called twice, dont know why... workaround to solve this problem
((CollectActivity) getActivity()).swipeFragment();
}
}
}
}
};
getContext().registerReceiver(udpMessages, new IntentFilter("UDP.MESSAGES.COLLECT"));
}
#Override
public void onPause() {
super.onPause();
getContext().unregisterReceiver(udpMessages);
}
#Override
public void onDestroyView() {
super.onDestroyView();
}
}

Android kankan-wheel modification

I am making a slot machine app and using kankan's wheel for the same. I want to modify the library such that when the rotation stops the item it will point shoud be the one that I set . I have done this but there is a glitch that shows that we have changed the actual image to the one that we want . How to achieve this?
Update:
I have researched a lot on this and if I am right , android scroll is based on duration and distance not items . From kankan's wheel library I can get current item .Now , I am trying to stop the animation as well as scroll , as soon as a certain duration has been reached and the item is the one that I want (through index) . But this is not working .Please help!!
GameActivity
public class GameActivity extends Activity {
float mDeviceDensity;
String mUuid, mTitle, mContent, mReward;
ImageButton play;
SlotMachineAdapter slotAdapter;
private List<HashMap<String, Object>> slotImages = new ArrayList<HashMap<String, Object>>();
ArrayList<String> imagesWinId = new ArrayList<String>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_filler_up_game);
DisplayMetrics display = getResources().getDisplayMetrics();
mDeviceDensity = display.density;
slotAdapter = new SlotMachineAdapter(this);
getPassedData();
setSoundPlayer(R.raw.clicks,true);
initWheel(R.id.slot_1, false, 0);
initWheel(R.id.slot_2, false, 1);
initWheel(R.id.slot_3, true, 2);
play = (ImageButton) findViewById(R.id.btn_mix);
play.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
shuffle(R.id.slot_1, 5000);
shuffle(R.id.slot_2, 7000);
shuffle(R.id.slot_3, 9000);
}
});
}
protected ImageLoader imageLoader;
ArrayList<SlotItem> arrListSlotItems;
private void getPassedData() {
try {
mUuid = getIntent().getStringExtra(getString(R.string.FILLER_UP_UUID));
imageLoader = ImageLoader.getInstance();
Uuid slotImagesExtra = (Uuid) (getIntent()
.getSerializableExtra(getString(R.string.FILLER_UP_IMAGES)));
arrListSlotItems = slotImagesExtra.getArrSlotItemArray();
for (int i = 0; i < arrListSlotItems.size(); i++)
downloadSlotImages(arrListSlotItems.get(i).getSlotId(), arrListSlotItems.get(i).getImageUrl());
} catch (Exception e) {
e.printStackTrace();
}
}
// Wheel scrolled flag
private boolean wheelScrolled = false;
// Wheel scrolled listener
OnWheelScrollListener scrolledListener = new OnWheelScrollListener() {
public void onScrollingStarted(WheelView wheel) {
wheelScrolled = true;
}
public void onScrollingFinished(WheelView wheel) {
wheelScrolled = false;
setStatus(wheel.getId(), getWheel(wheel.getId()).getWinningIndex());
}
};
// Wheel changed listener
private OnWheelChangedListener changedListener = new OnWheelChangedListener() {
public void onChanged(WheelView wheel, int oldValue, int newValue) {
if (!wheelScrolled) {
}
}
};
/**
* Updates status
*/
private void updateStatus() {
myThread();
}
public void myThread(){
Thread th=new Thread(){
#Override
public void run(){
try
{
Thread.sleep(2000);
GameActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
showAlertDialogWithSingleButton(GameActivity.this, mTitle, mContent, success);
}
});
}catch (InterruptedException e) {
// TODO: handle exception
}
}
};
th.start();
}
android.content.DialogInterface.OnClickListener success = new android.content.DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (mContent != null && mContent.contains("again"))
startHomeActivity();
else
startNewsActivity();
}
};
private void startHomeActivity() {
}
private void startNewsActivity() {
}
android.content.DialogInterface.OnClickListener fail = new android.content.DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//
}
};
public void showAlertDialogWithSingleButton(final Activity ctx, final String title, final String message,
DialogInterface.OnClickListener onClickListener) {
// show dialog
}
private void initWheel(int id, boolean monitorScroll, int itemIndex) {
Random randomGenerator = new Random();
int index = randomGenerator.nextInt(arrListSlotItems.size());
WheelView wheel = getWheel(id);
wheel.setViewAdapter(slotAdapter);
wheel.setCurrentItem((index ));
wheel.setVisibleItems(1);
wheel.setWinningIndex(itemIndex);
wheel.addChangingListener(changedListener);
wheel.addScrollingListener(scrolledListener);
wheel.setCyclic(true);
wheel.setEnabled(false);
}
private WheelView getWheel(int id) {
return (WheelView) findViewById(id);
}
private void setStatus(int id, int item) {
int index = 0;
for (int i = 0; i < arrListSlotItems.size(); i++) {
SlotItem d = arrListSlotItems.get(i);
if (d.getSlotId() != 0 && d.getSlotId() == Integer.parseInt(imagesWinId.get(item)))
index = arrListSlotItems.indexOf(d);
}
getWheel(id).setCurrentItem(index, true);
if (id == R.id.slot_3) {
if(player.isPlaying())
{
stopBackgroundAudio();
}
updateStatus();
}
}
private void shuffle(int id, int duration) {
WheelView wheel = getWheel(id);
wheel.scroll(450 + (int) (Math.random() * 50), duration);
}
private class SlotMachineAdapter extends AbstractWheelAdapter {
final int IMAGE_WIDTH = getImageWidth(mDeviceDensity);
final int IMAGE_HEIGHT = getImageHeight(mDeviceDensity);
private Context context;
/**
* Constructor
*/
public SlotMachineAdapter(Context context) {
this.context = context;
}
/**
* Loads image from resources
*/
private Bitmap loadImage(Bitmap bitmap) {
Bitmap scaled = Bitmap.createScaledBitmap(bitmap, IMAGE_WIDTH, IMAGE_HEIGHT, true);
return scaled;
}
#Override
public int getItemsCount() {
return slotImages.size();
}
// Layout params for image view
final LayoutParams params = new LayoutParams(IMAGE_WIDTH, IMAGE_HEIGHT);
#Override
public View getItem(int index, View cachedView, ViewGroup parent) {
ImageView img;
if (cachedView != null) {
img = (ImageView) cachedView;
} else {
img = new ImageView(context);
}
img.setPadding(0, 5, 0, 5);
img.setLayoutParams(params);
#SuppressWarnings("unchecked")
SoftReference<Bitmap> bitmapRef = (SoftReference<Bitmap>) slotImages.get(index).get("image");
Bitmap bitmap = bitmapRef.get();
if (bitmap == null) {
bitmap = loadImage(bitmap);
}
img.setImageBitmap(bitmap);
return img;
}
}
private int getImageWidth(float density) {
}
private int getImageHeight(float density) {
}
private void downloadSlotImages(final int id, String slotObj) {
//downloading slot images from server
}
}
This is the code. Through this code, when slot stops I want it to scroll some more untill it reaches the image position that I receaved from server. I can do this .But this is providing a lil glitch . Is there any way to stop scrolling when the image is reached as soon as certain duration is reached.
P.S. If you need anymore detail I can provide you.
P.P.S. Screenshots wont give you any detailed insight about the issue.
After days of searching I finally did it.All I had to do was set interpolater as LinearInterpolater and While setting setCurrentItem set animation as true.

How to update a textview in a dialog fragment from an activity?

It may be a silly question but I didn't find a good way to update a dialogfragment's textview from an activity in my android app.
What I'd like to do is to update the textview every second with a counter value and once the time elapsed, a Runnable closes the dialog fragment.
The dialog is closed once the time is elapsed, no problem but I cannot update the textview I want.
Here's my code for the dialog:
public class AlertDialog extends DialogFragment {
private String message = null;
private String title = null;
private ImageView imgV = null;
private TextView msgTv = null;
private TextView counterTv = null;
private Button okBtn = null;
private int imageId = 0;
public static int AUTOMATIC_CLOSE = 100001;
private AlertDialogListener mDialogListener;
public void setImage(int i){
imageId = i;
}
public void setContent(String ttl, String msg){
message = msg;
title = ttl;
}
public boolean hasContent(){
return message != null && title != null;
}
public AlertDialog(){
}
public void performClick(){
okBtn.performClick();
}
public void updateField(String text){
counterTv.setText(text);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.dialog, container);
msgTv = (TextView)v.findViewById(R.id.textDialog);
imgV = (ImageView)v.findViewById(R.id.imageDialog);
counterTv = (TextView)v.findViewById(R.id.timeCounterDialog);
if(imageId != 0)
imgV.setImageResource(imageId);
else
imgV.setImageResource(R.drawable.error_icon);
if(hasContent()){
msgTv.setText(message);
getDialog().setTitle(title);
}
else{
getDialog().setTitle("ERROR");
msgTv.setText("An unexcepted error occured");
}
okBtn = (Button)v.findViewById(R.id.validateButton);
okBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(mDialogListener != null){
mDialogListener.onFinishedDialog();
}
}
});
return v;
}
#Override
public void onStart() {
mDialogListener.onStartedDialog();
super.onStart();
}
#Override
public void onAttach(Activity activity) {
mDialogListener = (AlertDialogListener) activity;
super.onAttach(activity);
}
#Override
public void onDetach() {
mDialogListener = null;
super.onDetach();
}
public interface AlertDialogListener{
void onStartedDialog();
void onFinishedDialog();
}
}
And this is how I launch it:
class myActivity extends Activity implements AlertDialogListener{
protected void onCreate(Bundle savedInstanceState){
"""some init stuff"""
button.setOnClickListener(new View.OnClickListener() {
showAlertDialog();
}
}
#Override
public void onStartedDialog() {
AutoCloseRunnable mAutoClose = new AutoCloseRunnable();
mHandler.postDelayed(mAutoClose, 1000);
}
#Override
public void onFinishedDialog() {
this.finish();
}
private void showAlertDialog(){
FragmentManager fm = getFragmentManager();
mAlertDialog = new AlertDialog();
mAlertDialog.setContent("No Connection available", "Please enable your internet connection.");
mAlertDialog.setImage(R.drawable.error_icon);
mAlertDialog.show(fm, "fragment_alert");
}
private void updateAlertDialog(String text){
mAlertDialog.updateField(text);
}
private void autoCloseAlertDialog(){
mAlertDialog.performClick();
}
public class AutoCloseRunnable implements Runnable{
#Override
public void run() {
int closeCpt = 10;
while(closeCpt >= 0){
try {
Thread.sleep(1000);
updateAlertDialog("Will close automatically in " + closeCpt + " seconds.");
closeCpt--;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
autoCloseAlertDialog();
}
}
}
Does anyone know how to proceed?
I solved it, simply use asynctask it's easier to handle UI updates like this.

Categories

Resources