Android ShowcaseView not showing with recursion method - android

Straight to the point. I am trying to show coachmark series using ShowcaseView library by amlcurran: https://github.com/amlcurran/ShowcaseView
I can't get the coachmark showing. The problem is runCoachMark() method always returning null. runCoachMark() method run right after notifyDatasetChaned() on mMainAdapter.
I have tried to use Handler().postDelayed() and Thread.sleep() with no success.
Anyone can explain why it is happening and some solutions for this problem. Thank you.
private static final int COACHMARK_A = -3;
private static final int COACHMARK_B = -2;
private static final int COACHMARK_C = -1;
// ... some other coachmark type
private static final int END_COACHMARK = 0;
private static final int SCROLL_OFFSET = 56;
private static final long COACHMARK_DELAY = 200L;
private void runCoachMark(int type) {
if (type == END_COACHMARK) {
return;
}
View v = getCoachMarkView(type);
if (v == null) {
return;
}
showCoachMark(getActivity(), v, type);
}
#Nullable
private View getCoachMarkView(final int type) {
safeScrollTo(getPos(type), SCROLL_OFFSET);
return mMainList.getChildAt(0).findViewById(getCoachMarkId(type));
}
private void safeScrollTo(final int pos, final int offset) {
mMainList.setLayoutFrozen(true);
mLayoutManager.scrollToPositionWithOffset(pos, offset);
mMainList.setLayoutFrozen(false);
}
private int getCoachMarkId(int type) {
int id;
switch (type) {
case COACHMARK_A:
id = R.id.A;
break;
case COACHMARK_B:
id = R.id.B;
break;
case COACHMARK_C:
id = R.id.C;
break;
// ... some other types
default:
id = 0;
break;
return id;
}
private int getPos(int type) {
int pos;
switch (type) {
case COACHMARK_A:
pos = 1;
break;
case COACHMARK_B:
pos = 4;
break;
case COACHMARK_C:
pos = 5;
break;
// ... some other cases
default:
pos = 0;
break;
}
return pos;
}
private void showCoachMark(final Context context, final View v, final int type) {
new ShowcaseView.Builder(getActivity())
.setTarget(new ViewTarget(v.getId(), (Activity) context))
.setContentTitle(getTitle(type))
.setContentText(getDescription(type))
.setShowcaseDrawer(new CustomShowcaseView(v))
.setShowcaseEventListener(new OnShowcaseEventListener() {
#Override
public void onShowcaseViewHide(ShowcaseView showcaseView) {
}
#Override
public void onShowcaseViewDidHide(ShowcaseView showcaseView) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
runCoachMark(type++);
}
}, COACHMARK_DELAY);
}
#Override
public void onShowcaseViewShow(ShowcaseView showcaseView) {
}
#Override
public void onShowcaseViewTouchBlocked(MotionEvent motionEvent) {
}
})
.build();
}
}

I would share with you a new way to use showcaseview dynamically with recursive method
1) Create your ViewTargets, for example 4 targets (you can create n targets) and put targets into an array declared as a private attribute in your Activity class : private ViewTarget[] targets;
final ViewTarget target1 = new ViewTarget(textview1);
final ViewTarget target2 = new ViewTarget(textview2);
final ViewTarget target3 = new ViewTarget(textview3);
final ViewTarget target4 = new ViewTarget(textview4);
targets = new ViewTarget[] { target1, target2,target3,target4};
2) Create the recursive method :
private void toStep(final String title, final String description,Target target, final int i) {
final ShowcaseView.Builder showCaseBuilder = new ShowcaseView.Builder(ShowCaseActivity.this);
showCaseBuilder.setTarget(targets[i]);
showCaseBuilder.setContentTitle(title.replace("[i]", ""+i));
showCaseBuilder.setContentText(description.replace("[i]", ""+i));
showCaseBuilder.setShowcaseEventListener(new OnShowcaseEventListener() {
#Override
public void onShowcaseViewTouchBlocked(MotionEvent motionEvent) {
}
#Override
public void onShowcaseViewShow(ShowcaseView showcaseView) {
}
#Override
public void onShowcaseViewHide(ShowcaseView showcaseView) {
try {
toStep(title, description, targets[i+1], i+1);
} catch(Exception ex) {
}
}
#Override
public void onShowcaseViewDidHide(ShowcaseView showcaseView) {
}
});
showCaseBuilder.build();
}
3) Finally you can call the method that displays Showcases :
toStep("Title for showcase [i]", " Description for showcase [i] ",targets[0], 0);
I hope this will be helpful for you :)

Related

Android restore filter on custom adapter listview

Starting from one activity, I open another one and filter the result of a custom listview.
This is the first activity:
public class PersonaFragment extends Fragment {
private PersonaAdapter personaAdapter;
private ListView personeListView;
private ArrayList<Persona> personeList = new ArrayList<Persona>();
private ArrayList<String> listIdClas = new ArrayList<String>();
private final static int INSERT_REQUEST = 1;
private final static int FILTER_REQUEST = 2;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.persona_fragment, null);
setHasOptionsMenu(true);
personaAdapter = new PersonaAdapter(getActivity(), personeList, R.layout.persona_row_layout);
personeListView = view.findViewById(R.id.lvPersone);
personeListView.setAdapter(personaAdapter);
blsRequest request = new blsRequest(getActivity(), blsVolleyResponse());
request.add(blsUrl.listaPersone(), "00");
return view;
}
private void startFilterActivity() {
Intent intent = new Intent(getActivity(), PersonaFilterActivity.class);
intent.putStringArrayListExtra("listIdClas", this.listIdClas);
startActivityForResult(intent, FILTER_REQUEST);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == FILTER_REQUEST) {
if (resultCode == RESULT_OK) {
this.listIdClas = data.getStringArrayListExtra("listIdClas");
personaAdapter.filterManual(this.listIdClas);
}
}
}
private blsVolleyResponse blsVolleyResponse() {
return new blsVolleyResponse() {
#Override
public void onResponse(String result, String tag) {
switch (tag) {
case "00":
personeList = blsJSON.ParseList(result, tag);
personaAdapter.updateData(personeList);
break;
}
}
#Override
public void onError(VolleyError error, String tag) {
Toast.makeText(getActivity(), "Ops! Qualcosa è andato storto", Toast.LENGTH_SHORT).show();
blsLog.i("blsVolleyResponse.onError: TAG = " + tag + " ERROR = " + error);
}
};
}
}
and this is the filter activity:
public class PersonaFilterActivity extends AppCompatActivity {
private ClasseAdapter classeAdapter;
private ListView classiListView;
private ArrayList<Classe> classiList = new ArrayList<Classe>();
private ArrayList<String> listIdClas = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.persona_filter_activity);
Bundle extras = getIntent().getExtras();
if (extras != null) {
listIdClas = extras.getStringArrayList("listIdClas");
}
classiListView = findViewById(R.id.lvClassi);
classeAdapter = new ClasseAdapter(this, classiList);
classiListView.setAdapter(classeAdapter);
classiListView.addOnLayoutChangeListener(onListLoaded);
blsRequest request = new blsRequest(this, blsVolleyResponse());
request.add(blsUrl.listaClassi(), "00");
}
private View.OnLayoutChangeListener onListLoaded = new View.OnLayoutChangeListener() {
#Override
public void onLayoutChange(View view, int i, int i1, int i2, int i3, int i4, int i5, int i6, int i7) {
setFilter();
}
};
private void applyFilter() {
fillListId();
Intent returnIntent = new Intent();
returnIntent.putStringArrayListExtra("listIdClas", listIdClas);
setResult(Activity.RESULT_OK, returnIntent);
finish();
}
private void fillListId() {
listIdClas.clear();
for (int i = 0; i < classiListView.getChildCount(); i++) {
View child = classiListView.getChildAt(i);
Classe classe = (Classe) classiListView.getItemAtPosition(i);
Switch aSwitch = child.findViewById(R.id.swFlt);
if (aSwitch.isChecked())
listIdClas.add(classe.getId());
}
}
private void ReturnValue(int Result) {
Intent returnIntent = new Intent();
setResult(Result, returnIntent);
finish();
}
private void clearFilter() {
listIdClas.clear();
for (int i = 0; i < classiListView.getChildCount(); i++) {
View child = classiListView.getChildAt(i);
Switch aSwitch = child.findViewById(R.id.swFlt);
aSwitch.setChecked(false);
}
}
private void setFilter() {
for (int i = 0; i < classiListView.getChildCount(); i++) {
for (String idCat : listIdClas) {
View child = classiListView.getChildAt(i);
Switch aSwitch = child.findViewById(R.id.swFlt);
Classe classe = (Classe) classiListView.getItemAtPosition(i);
if (classe.getId().compareTo(idCat) == 0)
aSwitch.setChecked(true);
}
}
}
private blsVolleyResponse blsVolleyResponse() {
return new blsVolleyResponse() {
#Override
public void onResponse(String result, String tag) {
switch (tag) {
case "00":
classiList = blsJSON.ParseList(result, tag);
classeAdapter.updateData(classiList);
break;
}
}
#Override
public void onError(VolleyError error, String tag) {
Toast.makeText(PersonaFilterActivity.this, "Ops! Qualcosa è andato storto", Toast.LENGTH_SHORT).show();
blsLog.i("blsVolleyResponse.onError: TAG = " + tag + " ERROR = " + error);
}
};
}
}
As you can see I don't use:
classiListView.getCount()
but
classiListView.getChildCount()
Because there are a lot of items on filter listview and if I use "getCount()" I get an error like:
"Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference"
I don't have any problem to filter the custom adapter of the listview: using an array list I store the rows id that I selected and I apply them on the first activity listview. Right now I need to open the second activity and set checked the Switch object for each row (if it was/wasn't checked) but when I re-click the filter button to add other filters the filter item's listview aren't restored correctly, due to using "getChildCount()".
Hope I was clear. How do I perform it?

selectable RecyclerView performance issues

I am currently trying to achieve an app to edit weekly timeframes.
Like mechanical timers for sockets, but in my case for every weekday.
The granularity is in the first place secondary (i guess it will be 15 or 30min).
My approach was a RecyclerView with GridLayoutManager and an ArrayAdapter with Items for every Cell.
To select more cells you can longpress a cell and drag over others. To achieve this I used the Listeners of the following Library DragSelectRecyclerView.
It works pretty well and you can select the items quite good but especially on the emulator or older phones its very slow and laggy. In the debug logcat you can see also that the Choreographer has to skip many frames at rendering the View and on selection of multiple cells.
Is there an better approach to achieve such an behavior. Or is there any big mistake in the code which is very slow and crappy?
EDIT:
after changing notifyItemChanged(pos); to notifyItemRangeChanged(pos, pos); its way less laggy but still not performing as well as it should.
I also removed everything that was responsible for autoscrolling (which was a feature of the library i mentioned above) to make the code simpler.
Here the source of my Fragment
public class TestFragment extends Fragment
{
#BindView(R.id.gridView_hours) GridView gridView_hours;
#BindView(R.id.weekdays_container) LinearLayout weekdays_container;
private String[] hours = new String[]{"00:00", "01:00", "02:00", "03:00", "04:00", "05:00", "06:00", "07:00", "08:00", "09:00", "10:00", "11:00", "12:00", "13:00", "14:00", "15:00", "16:00", "17:00", "18:00", "19:00", "20:00", "21:00", "22:00", "23:00"};
private String[] hoursShort = new String[]{"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23"};
#Override
public void onCreate(#Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.fragment_test, container, false);
ButterKnife.bind(this, view);
for (int i = 1; i <= 7; i++)
{
RecyclerView recyclerView = new RecyclerView(getActivity());
initAdapter(recyclerView);
GridLayoutManager glm = new GridLayoutManager(getActivity(), 48, GridLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(glm);
weekdays_container.addView(recyclerView);
}
gridView_hours.setAdapter(new ArrayAdapter<String>(getActivity(), R.layout.hour_view, hoursShort));
// GridLayoutManager glm = new GridLayoutManager(getActivity(), 48, GridLayoutManager.VERTICAL, false);
// recyclerView.setLayoutManager(glm);
return view;
}
private void initAdapter(RecyclerView recyclerView)
{
TestAutoDataAdapter adapter = new TestAutoDataAdapter(getActivity(), 48);
recyclerView.setAdapter(adapter);
DragSelectionProcessor dragSelectionProcessor = new DragSelectionProcessor(new DragSelectionProcessor.ISelectionHandler() {
#Override
public HashSet<Integer> getSelection() {
return adapter.getSelection();
}
#Override
public boolean isSelected(int index) {
return adapter.getSelection().contains(index);
}
#Override
public void updateSelection(int start, int end, boolean isSelected, boolean calledFromOnStart) {
adapter.selectRange(start, end, isSelected);
}
});
DragSelectTouchListener dragSelectTouchListener = new DragSelectTouchListener()
.withSelectListener(dragSelectionProcessor);
recyclerView.addOnItemTouchListener(dragSelectTouchListener);
adapter.setClickListener(new TestAutoDataAdapter.ItemClickListener()
{
#Override
public void onItemClick(View view, int position)
{
adapter.toggleSelection(position);
}
#Override
public boolean onItemLongClick(View view, int position)
{
dragSelectTouchListener.startDragSelection(position);
return true;
}
});
}
}
and the RecyclerView.Adapter
public class TestAutoDataAdapter extends RecyclerView.Adapter<TestAutoDataAdapter.ViewHolder>
{
private int dataSize;
private Context context;
private ItemClickListener clickListener;
private HashSet<Integer> selected;
public TestAutoDataAdapter(Context context, int size)
{
this.context = context;
dataSize = size;
selected = new HashSet<>();
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(context).inflate(R.layout.test_cell, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position)
{
holder.tvText.setText("");
if (selected.contains(position))
holder.tvText.setBackgroundColor(Color.RED);
else
holder.tvText.setBackgroundColor(Color.WHITE);
}
#Override
public int getItemCount()
{
return dataSize;
}
// ----------------------
// Selection
// ----------------------
public void toggleSelection(int pos)
{
if (selected.contains(pos))
selected.remove(pos);
else
selected.add(pos);
notifyItemChanged(pos);
}
public void select(int pos, boolean selected)
{
if (selected)
this.selected.add(pos);
else
this.selected.remove(pos);
notifyItemRangeChanged(pos, pos);
}
public void selectRange(int start, int end, boolean selected)
{
for (int i = start; i <= end; i++)
{
if (selected)
this.selected.add(i);
else
this.selected.remove(i);
}
notifyItemRangeChanged(start, end - start + 1);
}
public void deselectAll()
{
// this is not beautiful...
selected.clear();
notifyDataSetChanged();
}
public void selectAll()
{
for (int i = 0; i < dataSize; i++)
selected.add(i);
notifyDataSetChanged();
}
public int getCountSelected()
{
return selected.size();
}
public HashSet<Integer> getSelection()
{
return selected;
}
// ----------------------
// Click Listener
// ----------------------
public void setClickListener(ItemClickListener itemClickListener)
{
clickListener = itemClickListener;
}
public interface ItemClickListener
{
void onItemClick(View view, int position);
boolean onItemLongClick(View view, int position);
}
// ----------------------
// ViewHolder
// ----------------------
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener
{
public TextView tvText;
public ViewHolder(View itemView)
{
super(itemView);
tvText = itemView.findViewById(R.id.tvText);
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
}
#Override
public void onClick(View view)
{
if (clickListener != null)
clickListener.onItemClick(view, getAdapterPosition());
}
#Override
public boolean onLongClick(View view)
{
if (clickListener != null)
return clickListener.onItemLongClick(view, getAdapterPosition());
return false;
}
}
}
the SelectTouchListener
public class DragSelectTouchListener implements RecyclerView.OnItemTouchListener
{
private static final String TAG = "DSTL";
private boolean mIsActive;
private int mStart, mEnd;
private int mLastStart, mLastEnd;
private OnDragSelectListener mSelectListener;
public DragSelectTouchListener()
{
reset();
}
/**
* sets the listener
* <p>
*
* #param selectListener the listener that will be notified when items are (un)selected
*/
public DragSelectTouchListener withSelectListener(OnDragSelectListener selectListener)
{
this.mSelectListener = selectListener;
return this;
}
// -----------------------
// Main functions
// -----------------------
/**
* start the drag selection
* <p>
*
* #param position the index of the first selected item
*/
public void startDragSelection(int position)
{
setIsActive(true);
mStart = position;
mEnd = position;
mLastStart = position;
mLastEnd = position;
if (mSelectListener != null && mSelectListener instanceof OnAdvancedDragSelectListener)
((OnAdvancedDragSelectListener)mSelectListener).onSelectionStarted(position);
}
// -----------------------
// Functions
// -----------------------
#Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e)
{
if (!mIsActive || rv.getAdapter().getItemCount() == 0)
return false;
int action = e.getAction();
switch (action)
{
case MotionEvent.ACTION_POINTER_DOWN:
case MotionEvent.ACTION_DOWN:
reset();
break;
}
return true;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e)
{
if (!mIsActive)
return;
int action = e.getAction();
switch (action)
{
case MotionEvent.ACTION_MOVE:
updateSelectedRange(rv, e);
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
reset();
break;
}
}
private void updateSelectedRange(RecyclerView rv, MotionEvent e)
{
updateSelectedRange(rv, e.getX(), e.getY());
}
private void updateSelectedRange(RecyclerView rv, float x, float y)
{
View child = rv.findChildViewUnder(x, y);
if (child != null)
{
int position = rv.getChildAdapterPosition(child);
if (position != RecyclerView.NO_POSITION && mEnd != position)
{
mEnd = position;
notifySelectRangeChange();
}
}
}
private void notifySelectRangeChange()
{
if (mSelectListener == null)
return;
if (mStart == RecyclerView.NO_POSITION || mEnd == RecyclerView.NO_POSITION)
return;
int newStart, newEnd;
newStart = Math.min(mStart, mEnd);
newEnd = Math.max(mStart, mEnd);
if (mLastStart == RecyclerView.NO_POSITION || mLastEnd == RecyclerView.NO_POSITION)
{
if (newEnd - newStart == 1)
mSelectListener.onSelectChange(newStart, newStart, true);
else
mSelectListener.onSelectChange(newStart, newEnd, true);
}
else
{
if (newStart > mLastStart)
mSelectListener.onSelectChange(mLastStart, newStart - 1, false);
else if (newStart < mLastStart)
mSelectListener.onSelectChange(newStart, mLastStart - 1, true);
if (newEnd > mLastEnd)
mSelectListener.onSelectChange(mLastEnd + 1, newEnd, true);
else if (newEnd < mLastEnd)
mSelectListener.onSelectChange(newEnd + 1, mLastEnd, false);
}
mLastStart = newStart;
mLastEnd = newEnd;
}
private void reset()
{
setIsActive(false);
if (mSelectListener != null && mSelectListener instanceof OnAdvancedDragSelectListener)
((OnAdvancedDragSelectListener)mSelectListener).onSelectionFinished(mEnd);
mStart = RecyclerView.NO_POSITION;
mEnd = RecyclerView.NO_POSITION;
mLastStart = RecyclerView.NO_POSITION;
mLastEnd = RecyclerView.NO_POSITION;
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept)
{
// ignore
}
public void setIsActive(boolean isActive)
{
this.mIsActive = isActive;
}
// -----------------------
// Interfaces and simple default implementations
// -----------------------
public interface OnAdvancedDragSelectListener extends OnDragSelectListener
{
/**
* #param start the item on which the drag selection was started at
*/
void onSelectionStarted(int start);
/**
* #param end the item on which the drag selection was finished at
*/
void onSelectionFinished(int end);
}
public interface OnDragSelectListener
{
/**
* #param start the newly (un)selected range start
* #param end the newly (un)selected range end
* #param isSelected true, it range got selected, false if not
*/
void onSelectChange(int start, int end, boolean isSelected);
}
}
and the Implementation of the needed Interface
public class DragSelectionProcessor implements DragSelectTouchListener.OnAdvancedDragSelectListener {
private ISelectionHandler mSelectionHandler;
private HashSet<Integer> mOriginalSelection;
private boolean mFirstWasSelected;
private boolean mCheckSelectionState = false;
public DragSelectionProcessor(ISelectionHandler selectionHandler)
{
mSelectionHandler = selectionHandler;
}
#Override
public void onSelectionStarted(int start)
{
mOriginalSelection = new HashSet<>();
Set<Integer> selected = mSelectionHandler.getSelection();
if (selected != null)
mOriginalSelection.addAll(selected);
mFirstWasSelected = mOriginalSelection.contains(start);
mSelectionHandler.updateSelection(start, start, !mFirstWasSelected, true);
}
#Override
public void onSelectionFinished(int end)
{
mOriginalSelection = null;
}
#Override
public void onSelectChange(int start, int end, boolean isSelected)
{
for (int i = start; i <= end; i++)
checkedUpdateSelection(i, i, isSelected ? !mFirstWasSelected : mOriginalSelection.contains(i));
}
private void checkedUpdateSelection(int start, int end, boolean newSelectionState)
{
if (mCheckSelectionState)
{
for (int i = start; i <= end; i++)
{
if (mSelectionHandler.isSelected(i) != newSelectionState)
mSelectionHandler.updateSelection(i, i, newSelectionState, false);
}
}
else
mSelectionHandler.updateSelection(start, end, newSelectionState, false);
}
public interface ISelectionHandler
{
Set<Integer> getSelection();
boolean isSelected(int index);
void updateSelection(int start, int end, boolean isSelected, boolean calledFromOnStart);
}
}
I wouldn't use notifyItemRangeChanged(pos, pos);, notifyDataSetChanged() etc. on each selection process.
Why won't you like this;
1.Took your recyclerview references in its adapter like this:
private RecyclerView mRecyclerView;
public TestAutoDataAdapter(Context context, int size, RecyclerView pRecyclerView){
this.mRecyclerView = pRecyclerView;
..
2.Set background color of the selected viewholder like this:
public void select(int pos, boolean selected){
// Get selected view holder from recyclerview
ViewHolder holder = recyclerview..findViewHolderForAdapterPosition(pos);
if (selected)
this.selected.add(pos);
else
this.selected.remove(pos);
//notifyItemRangeChanged(pos, pos);
holder.tvText.setBackgroundColor(selected ? Color.RED : Color.WHITE);
}
Change your whole selection process like this way and let me know the result.

Android View click freezes and not responding for 1 to 2 seconds

I have been creating a music player of my own. And when i click the list item, my view freezes for 1 to 2 seconds, How can i prevent my view from freezing.
I have tried asynctak, yet it hangs, anyway ActivityUtil.goPlayHome_Ser(getActivity(), finalI, gridType); just calls Service only.
I almost finished my music player app, but got struck in this one, need some help. Thank you.
Function
public static void goPlayHome_Ser(Context context, int position, String gridtype) {
Intent intent = new Intent(context, MediaService.class);
intent.setAction(MediaService.ACTION_PLAY_HOMEMAP + "");
intent.putExtra(Common.BUNDLE_SONG_POSITION, position);
intent.putExtra(Common.BUNDLE_MUSIC_LIST_TYPE, gridtype);
context.startService(intent);
}
MyRecycler Adapter
private class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.ViewHolder> {
private HashMap<String, List<Music>> map;
private Context mContext;
private List<String> headerList;
public HomeAdapter(Context context, HashMap<String, List<Music>> musicList) {
this.map = musicList;
this.mContext = context;
headerList = new ArrayList<>();
for (Map.Entry<String, List<Music>> entry : map.entrySet()) {
headerList.add(entry.getKey());
}
/*Collections.sort(headerList, new Comparator<String>() {
#Override
public int compare(String lhs, String rhs) {
return lhs.compareTo(rhs);
}
});*/
if (headerList.remove(Common.HOME_LIST_PLAYLIST)) {
headerList.add(Common.HOME_LIST_PLAYLIST);
}
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.adapter_home, null);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
final List<Music> musics = map.get(headerList.get(position));
holder.title.setText(headerList.get(position));
addGrids(mContext, holder, musics, headerList.get(position));
holder.gridMore.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
switch (headerList.get(position)) {
case Common.HOME_LIST_ALBUM:
PopupUtil.homeAlbumsPopup(getActivity(), view, musics);
break;
case Common.HOME_LIST_LATEST:
//PopupUtil.homeLatestPopup(getActivity(), view, musics);
PopupUtil.homeSongsPopup(getActivity(), view, Common.HOME_LIST_LATEST, musics);
break;
case Common.HOME_LIST_ALL_SONGS:
//PopupUtil.homeAllSongsPopup(getActivity(), view, musics);
PopupUtil.homeSongsPopup(getActivity(), view, Common.HOME_LIST_ALL_SONGS, musics);
break;
case Common.HOME_LIST_MOST_PLAYED:
PopupUtil.homeMostPlayedPopup(getActivity(), view, musics);
break;
case Common.HOME_LIST_PLAYLIST:
PopupUtil.homePlayListPopup(getActivity(), view, musics);
break;
}
}
});
}
#Override
public int getItemCount() {
return headerList.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
private TextView title;
private ImageView gridMore;
private LinearLayout grids;
public ViewHolder(View view) {
super(view);
this.title = (TextView) view.findViewById(R.id.adapter_home_grid_title);
this.gridMore = (ImageView) view.findViewById(R.id.adapter_home_grid_more);
this.grids = (LinearLayout) view.findViewById(R.id.adapter_home_grid);
}
}
private void addGrids(final Context context, ViewHolder holder, final List<Music> musics, final String gridType) {
holder.grids.removeAllViews();
int maxViewCount = musics.size() < 10 ? musics.size() : 10;
for (int i = 0; i < maxViewCount; i++) {
final int position = i;
View view = LayoutInflater.from(context).inflate(R.layout.view_custom_home_grid, null);
TextView gridTitle, gridArtist;
ImageView gridThumb;
gridTitle = (TextView) view.findViewById(R.id.home_grid_name);
gridArtist = (TextView) view.findViewById(R.id.home_grid_artist);
gridThumb = (ImageView) view.findViewById(R.id.home_grid_thumb);
switch (gridType) {
case Common.HOME_LIST_ALBUM:
gridTitle.setText(musics.get(i).getAlbum());
gridArtist.setText(musics.get(i).getArtist());
break;
case Common.HOME_LIST_ALL_SONGS:
gridTitle.setText(musics.get(i).getName());
gridArtist.setText(musics.get(i).getArtist());
break;
case Common.HOME_LIST_LATEST:
gridTitle.setText(musics.get(i).getName());
gridArtist.setText(musics.get(i).getArtist());
break;
case Common.HOME_LIST_MOST_PLAYED:
gridTitle.setText(musics.get(i).getName());
gridArtist.setText(musics.get(i).getArtist());
break;
case Common.HOME_LIST_PLAYLIST:
gridTitle.setText(musics.get(i).getPlaylist_name());
gridArtist.setText(musics.get(i).getArtist());
break;
}
final int finalI = i;
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ActivityUtil.goPlayHome_Ser(getActivity(), finalI, gridType);
}
});
ImageLoader.getInstance().displayImage(Util.getContentUri(musics.get(i).getAlbum_id()), gridThumb);
holder.grids.addView(view);
}
}
}
MediaService
public class MediaService extends Service implements MediaPlayer.OnErrorListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnBufferingUpdateListener, MediaPlayer.OnCompletionListener, AudioManager.OnAudioFocusChangeListener {
private static final String TAG = "MediaService";
public static final String BROADCAST_ACTION = "_broadcast_action";
public static final String BROADCAST_TYPE = "_broadcast_type";
public static final int ACTION_INITIALIZE = 1000;
public static final int ACTION_PLAY = 1001;
public static final int ACTION_PAUSE = 1002;
public static final int ACTION_TOGGLE = 1003;
public static final int ACTION_SEEK = 1004;
public static final int ACTION_PREV = 1006;
public static final int ACTION_NEXT = 1007;
public static final int ACTION_NOIFY_SHOW = 1008;
public static final int ACTION_NOIFY_HIDE = 1009;
public static final int ACTION_QUEUE = 1010;
public static final int ACTION_PLAY_NEXT = 1011;
public static final int ACTION_QUEUE_REMOVE_CURRENT_SONG = 1012;
public static final int ACTION_QUEUE_CHANGE_SONG = 1013;
public static final int ACTION_STORAGE_REMOVE_CURRENT_SONG = 1014;
public static final int ACTION_INIIALIZE_HOMEMAP = 1015;
public static final int ACTION_PLAY_HOMEMAP = 1016;
public static final int MUSIC_INITIALIZE_REPLY = 2000;
public static final int MUSIC_PLAY_REPLY = 2001;
public static final int MUSIC_PAUSE_REPLY = 2002;
public static final int MUSIC_SEEK_REPLY = 2003;
public static final int MUSIC_ERROR_REPLY = 2004;
public static final int MUSIC_QUEUELIST_REPLY = 2005;
public static final int MUSIC_HOMEFRAG_REPLY = 2006;
public static final int FOREGROUND_NOTIFICATION_ID = 3000;
private MediaPlayer mediaPlayer;
private AudioManager audioManager;
private Handler handler;
private Mediaobj mediaobj;
private NotificationCompat.Builder builder;
private NotificationManager notificationManager;
private HashMap<String, List<Music>> mHomeMap;
#Override
public void onCreate() {
super.onCreate();
audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
handler = new Handler();
Log.d(TAG, "onCreate called");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
int action = Integer.parseInt(intent.getAction());
Log.d(TAG, "onStartCommand -> " + String.valueOf(action));
switch (action) {
case ACTION_INITIALIZE:
if (mediaPlayer == null) {
Log.d(TAG, "Mediaplayer Initializing");
initializeMediaPlayer();
initializeMediaObj();
} else {
Log.d(TAG, "Mediaplayer already initialized");
initalizeReply();
}
break;
case ACTION_PLAY:
mediaobj.queueList.clear();
Bundle bundle = intent.getBundleExtra(Common.BUNDLE_INTENT);
List<Music> queues = (List<Music>) bundle.getSerializable(Common.BUNDLE_MUSIC_LIST_DATA);
if (PrefUtil.getShuffleIcon(getApplicationContext()) == R.drawable.ic_action_shuffle) {
Collections.shuffle(queues);
}
mediaobj.queueList = queues;
mediaobj.songPosition = 0;
mediaobj.music = mediaobj.queueList.get(mediaobj.songPosition);
play();
Dbhelper.getInstance(getApplicationContext()).removeQueues();
Dbhelper.getInstance(getApplicationContext()).addQueues(mediaobj.queueList);
break;
case ACTION_PAUSE:
pause();
break;
case ACTION_TOGGLE:
togglePlay();
break;
case ACTION_SEEK:
int seekPos = intent.getExtras().getInt(Common.BUNDLE_MUSIC_SEEK_POS);
mediaPlayer.seekTo(seekPos);
PrefUtil.saveMusicResumePosition(getApplicationContext(), mediaPlayer.getCurrentPosition());
seekReply();
break;
case ACTION_PREV:
if (mediaobj.hasPrev) {
mediaobj.songPosition--;
Dbhelper.getInstance(getApplicationContext()).updateQueueSongFlag(mediaobj.music.get_id(), false);
mediaobj.music = mediaobj.queueList.get(mediaobj.songPosition);
}
play();
break;
case ACTION_NEXT:
if (mediaobj.hasNext) {
mediaobj.songPosition++;
Dbhelper.getInstance(getApplicationContext()).updateQueueSongFlag(mediaobj.music.get_id(), false);
mediaobj.music = mediaobj.queueList.get(mediaobj.songPosition);
/*if (mediaPlayer.isPlaying()) {
play();
} else {
play();
pause();
}*/
play();
}
break;
case ACTION_NOIFY_SHOW:
createRemoteNotification(true);
break;
case ACTION_NOIFY_HIDE:
createRemoteNotification(false);
break;
case ACTION_QUEUE:
if (intent.getSerializableExtra(Common.BUNDLE_MUSIC_LIST_DATA) != null) {
List<Music> musics = (List<Music>) intent.getSerializableExtra(Common.BUNDLE_MUSIC_LIST_DATA);
if (mediaobj != null && mediaobj.queueList != null && musics != null) {
mediaobj.queueList.addAll(musics);
}
}
Dbhelper.getInstance(getApplicationContext()).removeQueues();
Dbhelper.getInstance(getApplicationContext()).addQueues(mediaobj.queueList);
queueReply();
break;
case ACTION_PLAY_NEXT:
if (intent.getSerializableExtra(Common.BUNDLE_MUSIC_LIST_DATA) != null) {
List<Music> musics = (List<Music>) intent.getSerializableExtra(Common.BUNDLE_MUSIC_LIST_DATA);
if (mediaobj != null && mediaobj.queueList != null && musics != null) {
int songPos = mediaobj.songPosition;
for (Music music : musics) {
songPos++;
mediaobj.queueList.add(mediaobj.songPosition + 1, music);
}
}
queueReply();
}
Dbhelper.getInstance(getApplicationContext()).removeQueues();
Dbhelper.getInstance(getApplicationContext()).addQueues(mediaobj.queueList);
break;
case ACTION_QUEUE_REMOVE_CURRENT_SONG:
Dbhelper.getInstance(getApplicationContext()).removeQueue(String.valueOf(mediaobj.music.get_id()));
mediaobj.queueList.remove(mediaobj.songPosition);
mediaobj.music = mediaobj.queueList.get(mediaobj.songPosition);
if (mediaPlayer.isPlaying()) {
play();
} else {
pause();
}
Dbhelper.getInstance(getApplicationContext()).updateQueueSongFlag(mediaobj.music.get_id(), true);
break;
case ACTION_QUEUE_CHANGE_SONG:
int songPosition = intent.getIntExtra(Common.BUNDLE_SONG_POSITION, mediaobj.songPosition);
if (songPosition == mediaobj.songPosition) {
togglePlay();
} else {
mediaobj.songPosition = songPosition;
mediaobj.music = mediaobj.queueList.get(mediaobj.songPosition);
play();
}
break;
case ACTION_STORAGE_REMOVE_CURRENT_SONG:
String path = mediaobj.music.getPath();
Dbhelper.getInstance(getApplicationContext()).removeQueue(String.valueOf(mediaobj.music.get_id()));
mediaobj.queueList.remove(mediaobj.songPosition);
mediaobj.music = mediaobj.queueList.get(mediaobj.songPosition);
if (mediaPlayer.isPlaying()) {
play();
} else {
pause();
}
Dbhelper.getInstance(getApplicationContext()).updateQueueSongFlag(mediaobj.music.get_id(), true);
Util.removeMp3FromStorage(path);
queueReply();
break;
case ACTION_INIIALIZE_HOMEMAP:
if (mHomeMap == null) {
mHomeMap = Util.getHomeHash(getApplicationContext());
}
Intent homeMapIntent = new Intent(BROADCAST_ACTION);
homeMapIntent.putExtra(BROADCAST_TYPE, MUSIC_HOMEFRAG_REPLY);
homeMapIntent.putExtra(Common.BUNDLE_HOMEFRAG_MAP, mHomeMap);
sendBroadcastMsg(homeMapIntent);
break;
case ACTION_PLAY_HOMEMAP: {
if (mHomeMap != null) {
int position = intent.getIntExtra(Common.BUNDLE_SONG_POSITION, 0);
String gridType = intent.getStringExtra(Common.BUNDLE_MUSIC_LIST_TYPE);
if (!TextUtils.equals(gridType, Common.HOME_LIST_PLAYLIST) && !TextUtils.equals(gridType, Common.HOME_LIST_ALBUM)) {
List<Music> musicList = mHomeMap.get(gridType);
mediaobj.queueList.clear();
mediaobj.queueList.addAll(musicList.subList(position, musicList.size() - 1));
mediaobj.music = mediaobj.queueList.get(0);
mediaobj.songPosition = 0;
play();
Dbhelper.getInstance(getApplicationContext()).removeQueues();
Dbhelper.getInstance(getApplicationContext()).addQueues(mediaobj.queueList);
}
}
}
default: {
}
}
return Service.START_NOT_STICKY;
}}
After looking at your code, I guess that you missing some points:
1. Your Service runs in main thread (UI thread). Check Service Guide
Caution: A service runs in the main thread of its hosting process—the service does not create its own thread and does not run in a separate process (unless you specify otherwise). This means that, if your service is going to do any CPU intensive work or blocking operations (such as MP3 playback or networking), you should create a new thread within the service to do that work
Look at your Database operations, if I do not misunderstand, you should avoid Database interaction in main thread, because I will take time and make your app not responsive.
Dbhelper.getInstance(getApplicationContext()).removeQueues(); Dbhelper.getInstance(getApplicationContext()).addQueues(mediaobj.queueList);
You must be working on Main UI thread which blocks/hangs screen. So please use
Another Thread
AsyncTask AsyncTask Tutorial
Or if you use Adapter binding of images.
Then go for lazy loading concept. Where images are loaded lazy, meaning your main thread is not blocked.

RecyclerView fling and move not smooth

i am chinese coder.i am not good at english,so just try hard to describe the question. thank you very much for your answer.
when i first into activity with RecyclerView and scroll,it is not smooth especially showing next item next ,but when i have scrolled the Recyclerview,it is work,and smooth . some coder say we can't do much work on onCreateViewHolder() and onBindViewHolder() , but i can not get it.
here is my code:
fragment
public class HomeFragment extends RefreshableFragment implements IHomeView {
#Bind(R.id.refresh_view)
PullToRefreshRecyclerView refresh_view;
private RecyclerView refreshableView;
private HomePresenter homePresenter;
#Override
public View initSuccessView() {
View view = View.inflate(getContext(), R.layout.fragment_refreshable_success_recyclerview, null);
ButterKnife.bind(this, view);
initRefreshLayout();
initRecyclerView();
return view;
}
/**
* 初始化可刷新控件
*/
private void initRefreshLayout() {
refresh_view.setMode(PullToRefreshBase.Mode.BOTH);
refresh_view.setOnRefreshListener(new PullToRefreshBase.OnRefreshListener2<RecyclerView>() {
#Override
public void onPullDownToRefresh(PullToRefreshBase<RecyclerView> refreshView) {
homePresenter.refresh();
}
#Override
public void onPullUpToRefresh(PullToRefreshBase<RecyclerView> refreshView) {
homePresenter.loadMore();
}
});
}
/**
* 初始化RecyclerView控件
*/
private void initRecyclerView() {
refreshableView = refresh_view.getRefreshableView();
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext(),LinearLayoutManager.VERTICAL,false);
SpaceItemDecoration decor = new SpaceItemDecoration(2);
refreshableView.addItemDecoration(decor);
refreshableView.setLayoutManager(layoutManager);
refreshableView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int childCount = recyclerView.getChildCount();
for (int i = 0; i < childCount; i++) {
View view = recyclerView.getChildAt(i);
RecyclerView.ViewHolder holder = recyclerView.getChildViewHolder(view);
switch (holder.getItemViewType()){
case HomeAdapter.TYPE_TOPIC:
HomeTopicViewHolder topicViewHolder = (HomeTopicViewHolder) holder;
topicViewHolder.setParentHeight(recyclerView.getHeight());
topicViewHolder.setOffset();
}
}
}
});
}
#Override
protected void requestNetwork() {
homePresenter = new HomePresenter(getContext(),this,null);
homePresenter.init();
}
#Override
public RecyclerView getRecyclerView() {
return refreshableView;
}
#Override
public RefreshView getRefreshView() {
return getParentRefreshView();
}
#Override
public void onRefreshFinish() {
if(refresh_view.isRefreshing()){
refresh_view.onRefreshComplete();
}
}
#Override
public void onLordMoreFinish() {
}
}
presenter
public class HomePresenter extends BasePresenter<IHomeView> implements IHomePresenter, StringLoaderCallback {
private Gson gson;
private HomeAdapter homeAdapter;
private final Pagination pagination;
public HomePresenter(Context context,IHomeView homeView,Bundle bundle) {
super(context,homeView,bundle);
gson = new Gson();
homeAdapter = new HomeAdapter();
getPresenterView().getRecyclerView().setAdapter(homeAdapter);
pagination = new Pagination();
pagination.setLimit(10);
pagination.setOffset(0);
}
#Override
public void init() {
String bannerUrl = ServerAPI.Home.buildHomeBannerUrl();
NetworkStringLoader.getInstance(context).sendGetStringRequest(bannerUrl, null, bannerUrl, this);
String topicUrl = ServerAPI.Home.buildHomeTopicUrl();
NetworkStringLoader.getInstance(context).sendGetStringRequest(topicUrl, null, topicUrl, this);
String routeUrl = ServerAPI.Home.buildHomeRouteUrl();
NetworkStringLoader.getInstance(context).sendGetStringRequest(routeUrl, pagination.getMap(), REFRESH, this);
}
#Override
public void loadMore() {
String routeUrl = ServerAPI.Home.buildHomeRouteUrl();
pagination.setOffset(pagination.getTotal());
pagination.setLimit(10);
NetworkStringLoader.getInstance(context).sendGetStringRequest(routeUrl, pagination.getMap(), LOADMORE, this);
}
#Override
public void refresh() {
pagination.setOffset(0);
pagination.setLimit(10);
pagination.clearTotal();
init();
}
#Override
public void onLoadFinished(String url,Map<String,String> params, String data,Object tag) {
if(url.equals(ServerAPI.Home.buildHomeBannerUrl())){
Log.i(url,data);
HomeBanner.HomeBannerLists homeBannerLists = gson.fromJson(data,HomeBanner.HomeBannerLists.class);
homeAdapter.setBanners(homeBannerLists.list);
}
if(url.equals(ServerAPI.Home.buildHomeTopicUrl())){
Log.i(url,data);
HomeTopic.HomeTopicLists homeTopicLists = gson.fromJson(data,HomeTopic.HomeTopicLists.class);
homeAdapter.setTopics(homeTopicLists.list);
}
if(url.equals(ServerAPI.Home.buildHomeRouteUrl())){
Log.i(url,data);
int mode = (int) tag;
HomeRoute.HomeRouteLists homeRouteLists = gson.fromJson(data, HomeRoute.HomeRouteLists.class);
if (mode == REFRESH){
homeAdapter.setRoutes(homeRouteLists.list);
} else if(mode == LOADMORE){
homeAdapter.appendRoutes(homeRouteLists.list);
}
pagination.appendTotal(homeRouteLists.list.size());
}
getPresenterView().getRefreshView().setCurrentState(RefreshView.STATE_SUCCESS);
getPresenterView().onRefreshFinish();
}
#Override
public void onLoadError(VolleyError error) {
Log.i("error",error.getMessage());
}
}
adapter
public class HomeAdapter extends RecyclerView.Adapter {
public static final int TYPE_BANNER = 0;
public static final int TYPE_TOPIC = 1;
public static final int TYPE_ROUTE = 2;
private List<HomeBanner> banners = new ArrayList<>();
private List<HomeTopic> topics = new ArrayList<>();
private List<HomeRoute> routes = new ArrayList<>();
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType){
case TYPE_BANNER:
View bannerView = HomeBannerViewHolder.getView(parent.getContext());
return new HomeBannerViewHolder(bannerView);
case TYPE_TOPIC:
View topicView = View.inflate(parent.getContext(), R.layout.item_home_topic,null);
// View topicView = HomeTopicViewHolder.getView(parent.getContext());
return new HomeTopicViewHolder(topicView);
case TYPE_ROUTE:
View routeView = View.inflate(parent.getContext(), R.layout.item_home_route,null);
// View routeView = HomeRouteViewHolder.getView(parent.getContext());
return new HomeRouteViewHolder(routeView);
default:
// View defaultView = new View(parent.getContext());
View view = EmptyViewHolder.getView(parent.getContext());
return new EmptyViewHolder(view);
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if(position == 0){
onBindBannerViewHolder(holder);
}else if(position>0 && position<topics.size()+1){
onBindTopicViewHolder(holder,position-1);
}else {
onBindRouteViewHolder(holder,position-topics.size()-1);
}
}
private void onBindRouteViewHolder(RecyclerView.ViewHolder holder, int position) {
HomeRouteViewHolder routeViewHolder = (HomeRouteViewHolder) holder;
routeViewHolder.setData(routes.get(position));
}
private void onBindTopicViewHolder(RecyclerView.ViewHolder holder,int position) {
HomeTopicViewHolder topicViewHolder = (HomeTopicViewHolder) holder;
topicViewHolder.setData(topics.get(position));
}
private void onBindBannerViewHolder(RecyclerView.ViewHolder holder) {
HomeBannerViewHolder bannerViewHolder = (HomeBannerViewHolder) holder;
bannerViewHolder.setData(banners);
}
#Override
public int getItemCount() {
return 1 + topics.size()+routes.size();
}
#Override
public int getItemViewType(int position) {
if(position == 0){
return TYPE_BANNER;
}else if(position<topics.size()+1){
return TYPE_TOPIC;
}else {
return TYPE_ROUTE;
}
}
public void setBanners(List<HomeBanner> list){
banners.clear();
banners.addAll(list);
notifyDataSetChanged();
}
public void setTopics(List<HomeTopic> list) {
topics.clear();
topics.addAll(list);
notifyDataSetChanged();
}
public void setRoutes(List<HomeRoute> list) {
routes.clear();
routes.addAll(list);
notifyDataSetChanged();
}
public void appendRoutes(List<HomeRoute> list) {
routes.addAll(routes.size(),list);
notifyItemRangeInserted(getItemCount(),list.size());
}
}
holder
public class HomeTopicViewHolder extends BaseViewHolder<HomeTopic> {
private static SimpleDraweeView content_iv ;
private static TextView home_topic_title ;
private static TextView home_topic_discription ;
private int height;
public static View getView(Context context) {
View topicView = View.inflate(context, R.layout.item_home_topic,null);
return topicView;
}
public HomeTopicViewHolder(View itemView) {
super(itemView);
content_iv = (SimpleDraweeView) itemView.findViewById(R.id.home_topic_iv);
if(content_iv!=null){
content_iv = (SimpleDraweeView) itemView.findViewById(R.id.home_topic_iv);
}
if(home_topic_title!=null){
home_topic_title = (TextView) itemView.findViewById(R.id.home_topic_title);
}
if(home_topic_discription!=null){
home_topic_discription = (TextView) itemView.findViewById(R.id.home_topic_discription);
}
if(height==0){
SharedPreferences sp = SharedPreferenceHelper.getInstance().getSharedPreference(itemView.getContext(), SharedPreferenceHelper.EnumSPName.CONFIG);
int scale = sp.getInt(SharedPreferenceHelper.EnumSPName.windowWidth, 0);
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(scale,scale);
content_iv.setLayoutParams(layoutParams);
}
}
#Override
protected void inflateView(HomeTopic data) {
NetworkImageLoader loader = NetworkImageLoader.getInstance();
loader.setUrlToSimpleDraweeView(data.getImage(),content_iv);
home_topic_title.setText(data.getName());
home_topic_discription.setText(String.format(getResources().getString(R.string.guider_route),data.getGuide(), data.getRoute()));
}
public void setOffset() {
int itemViewHeight = itemView.getHeight();
int imageViewHeight = content_iv.getHeight();
int parentOffsetMax = (getParentHeight() + itemViewHeight) / 2;
int offsetMax = imageViewHeight - itemViewHeight;
float y = itemView.getY();
float location = y + itemViewHeight/2;
float v = location - getParentHeight() / 2;
float percent = v/parentOffsetMax;
int margin = (int) ((offsetMax/2)*(percent + 1));
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) content_iv.getLayoutParams();
layoutParams.setMargins(0,-margin,0,0);
content_iv.setLayoutParams(layoutParams);
}
public void setParentHeight(int height) {
this.height = height;
}
public int getParentHeight() {
return height;
}
}

PullToRefreshAttacher.OnRefreshListener cannot be resolved to a type

am building an open source project, here is its link
http://slidese.github.io/slidese/2013/11/25/update_listview_item.html
I've imported all library projects which it is using into eclipse. All are fine except PullToRefresh library. it is giving me the error "PullToRefreshAttacher.OnRefreshListener cannot be resolved to a type" where fragment implements it
2nd error is at
mPullToRefreshAttacher.addRefreshableView(mListview, this);
it says "The method addRefreshableView(View, ViewDelegate) in the type PullToRefreshAttacher is not applicable for the arguments (ListView, ContentFragment)"
3rd error is at
#Override
public void onRefreshStarted(View view) {
Intent intent = new Intent(getActivity(), DownloaderService.class);
intent.putExtra(DownloaderService.EXTRA_USER_INITIATED, true);
getActivity().startService(intent);
}
It is asking me to remove override annotation. here is complete code of fragment.
public class ContentFragment extends Fragment implements PullToRefreshAttacher.OnRefreshListener {
private final String TAG = "ContentFragment";
public static final String CONTENT_MODE = "content_mode";
public static final int MODE_ADFREE = 0;
public static final int MODE_PREMIUM = 1;
private StartActivity mListener;
private PullToRefreshAttacher mPullToRefreshAttacher;
private UpdaterAsyncTask mUpdater;
private int mScrollState = OnScrollListener.SCROLL_STATE_IDLE;
ListView mListview;
Button mPlayButton;
ContentAdapter mAdapter;
int mMode;
Map<String, UpdateHolder> mUpdates = new HashMap<String, UpdateHolder>();
public ContentFragment() {
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (StartActivity) activity;
Log.d(TAG, "Attached podcast list fragment");
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must be the StartActivity");
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_content, null);
mListview = (ListView) view.findViewById(android.R.id.list);
mListview.setEmptyView(view.findViewById(R.id.empty_list_view));
mListview.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
mListview.setMultiChoiceModeListener(new MultiChoiceModeListener() {
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.contextual_menu_content, menu);
return true;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
if (item.getItemId() == R.id.action_delete) {
SparseBooleanArray checked = mListview.getCheckedItemPositions();
Content[] params = new Content[checked.size()];
int index = 0;
int first = mListview.getFirstVisiblePosition();
int last = mListview.getLastVisiblePosition();
for (int i = 0; i < mListview.getCount(); i++) {
if (checked.get(i)) {
params[index++] = (Content)mListview.getItemAtPosition(i);
if (i >= first && i <= last) {
View view = mListview.getChildAt(i-first);
Animation animation = AnimationUtils.loadAnimation(getActivity(), android.R.anim.slide_out_right);
animation.setDuration(200);
//animation.setFillAfter(true);
animation.setStartOffset(100 * (index) );
view.startAnimation(animation);
}
}
}
new AsyncTask<Content, Void, Void>() {
#Override
protected Void doInBackground(Content... params) {
for (Content content : params) {
File file = Utils.getFilepath(content.getFilename());
file.delete();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
mAdapter.notifyDataSetChanged();
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
mode.finish();
return true;
}
return false;
}
#Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
}
});
mListview.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View view, int position, long id) {
Content content = mAdapter.getItem(position);
mListener.showContentDetails(content);
}
});
mListview.setOnScrollListener(new OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
mScrollState = scrollState;
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
});
mPullToRefreshAttacher = ((StartActivity) getActivity()).getPullToRefreshAttacher();
mPullToRefreshAttacher.addRefreshableView(mListview, this);
mMode = getArguments().getInt(CONTENT_MODE);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
#Override
public void onPause() {
super.onPause();
if (mUpdater != null)
mUpdater.stop();
}
#Override
public void onResume() {
super.onResume();
updateAdapter();
mUpdater = new UpdaterAsyncTask();
mUpdater.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void)null);
}
public void refresh() {
updateAdapter();
}
public void replaceCurrentlyPlayingContent() {
GlobalContext.INSTANCE.replaceCurrentlyPLayingContent(mAdapter.getObjects(), mListener.getCurrentTrack());
}
private void updateAdapter() {
Log.d(TAG, "updateAdapter");
//new FetchContentAsyncTask(mMode).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
final String mp3 = mListener.getSavedStateMp3();
final boolean isPlaying = mListener.getSavedStateIsPlaying();
final boolean isPaused = mListener.getSavedStateIsPaused();
List<Content> listOfContent = GlobalContext.INSTANCE.getCachedContent(mMode, mp3, isPlaying, isPaused);
mAdapter = new ContentAdapter(getActivity(), R.layout.list_item_card, listOfContent);
mListview.setAdapter(mAdapter);
}
#Override
public void onRefreshStarted(View view) {
Intent intent = new Intent(getActivity(), DownloaderService.class);
intent.putExtra(DownloaderService.EXTRA_USER_INITIATED, true);
getActivity().startService(intent);
}
private class UpdaterAsyncTask extends AsyncTask<Void, Void, Void> {
boolean isRunning = true;
public void stop() {
isRunning = false;
}
#Override
protected Void doInBackground(Void... params) {
while (isRunning) {
/*
Map<String, UpdateHolder> map = gatherMetadata();
publishProgress(map);
*/
updateCurrentAdapterContent();
publishProgress();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void onProgressUpdate(Void... params) {
super.onProgressUpdate();
if (mScrollState == OnScrollListener.SCROLL_STATE_IDLE) {
// http://stackoverflow.com/questions/2123083/android-listview-refresh-single-row
int start = mListview.getFirstVisiblePosition();
for(int i = start, j = mListview.getLastVisiblePosition(); i<=j; i++) {
View view = mListview.getChildAt(i-start);
if (((Content)mListview.getItemAtPosition(i)).dirty) {
Log.v(TAG, "Content is dirty");
mListview.getAdapter().getView(i, view, mListview);
}
}
}
}
}
private void updateCurrentAdapterContent() {
List<Content> listOfContent = mAdapter.getObjects();
Map<String, UpdateHolder> map = new HashMap<String, UpdateHolder>();
DownloadManager.Query q = new DownloadManager.Query();
q.setFilterByStatus(DownloadManager.STATUS_PENDING | DownloadManager.STATUS_RUNNING);
try {
Cursor cursor = ContentDownloadManager.INSTANCE.query(q);
while (cursor.moveToNext()) {
//long id = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_ID));
String uri = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_URI));
int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
int downloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
int total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
float progress = (float)downloaded/(float)total;
UpdateHolder holder = new UpdateHolder();
holder.progress = progress;
holder.status = status;
map.put(uri, holder);
}
cursor.close();
final Content currentContent = mListener.getCurrentTrack();
final boolean isPlaying = mListener.isPlaying();
final boolean isPaused = mListener.isPaused();
for (Content content : listOfContent) {
// First update any download progress we might have for this specific content item
UpdateHolder holder = map.get(content.mp3);
if (holder != null) {
if (content.downloadProgress != holder.progress) {
content.downloadProgress = holder.progress;
content.dirty = true;
}
if (content.downloadStatus != holder.status) {
content.downloadStatus = holder.status;
content.dirty = true;
}
}
else {
if (content.downloadProgress != 0f) {
content.downloadProgress = 0f;
content.dirty = true;
}
if (content.downloadStatus != -1) {
content.downloadStatus = -1;
content.dirty = true;
}
}
// Update with elapsed (to be done)
// File exists?
File file = Utils.getFilepath(content.getFilename());
if (content.exists != file.exists()) {
content.exists = file.exists();
content.dirty = true;
}
// Is this the currently playing content
if (currentContent != null && content.mp3.equals(currentContent.mp3)) {
if (content.isPlaying != isPlaying) {
content.isPlaying = isPlaying;
content.dirty = true;
}
if (content.isPaused != isPaused) {
content.isPaused = isPaused;
content.dirty = true;
}
}
else {
if (content.isPlaying != false) {
content.isPlaying = false;
content.dirty = true;
}
if (content.isPaused != false) {
content.isPaused = false;
content.dirty = true;
}
}
if (content.dirty) {
DatabaseManager.getInstance().createOrUpdateContent(content);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public class UpdateHolder {
public String mp3;
public int status;
public boolean played;
public float progress;
public boolean exists = false;
public boolean isPlaying = false;
public boolean isPaused = false;
//public int elapsed;
//public int duration;
}
}
I couldn't find the issue in it. I'm stuck here for last 40 hours. Please help. Thank you!
Maybe you are using old version of the library. I found that PullToRefreshAttacher doesn't contain OnRefreshListener. (https://github.com/chrisbanes/ActionBar-PullToRefresh/blob/master/library/src/main/java/uk/co/senab/actionbarpulltorefresh/library/PullToRefreshAttacher.java)
Try to import uk.co.senab.actionbarpulltorefresh.library.listeners.OnRefreshListener; and use it instead of PullToRefreshAttacher.OnRefreshListener.

Categories

Resources