I am a beginner who am writing a code that consists of two activities. Both have their own Fragments. On the first activity (in its fragment), the user input some fields. The result will be displayed on the second activity (in its list fragment).
I have tried to get state manually using bundle. And now, I am using callback to do that. However, I got an error message java.lang.ClassCastException: Activity must implement fragment's callbacks.
The first activity is:
public class AssetRegistrationInfoPage extends Page {
public static final String ASSET_TYPE_NAME_KEY = "assetTypeName";
public static final String ASSET_ID_DATA_KEY = "assetID";
public static final String PROJECT_CODE_DATA_KEY = "projectCode";
public static final String REMARK_DATA_KEY = "remark";
public AssetRegistrationInfoPage(ModelCallbacks callbacks, String title) {
super(callbacks, title);
}
#Override
public Fragment createFragment() {
return AssetRegistrationInfoFragment.create(getKey());
}
#Override
public void getReviewItems(ArrayList<ReviewItem> dest) {
dest.add(new ReviewItem("Nama Asset", mData.getString(ASSET_TYPE_NAME_KEY), getKey(), 0, null));
dest.add(new ReviewItem("Kode Asset", mData. getString(ASSET_ID_DATA_KEY), getKey(), 0, null));
dest.add(new ReviewItem("Kode Project", mData.getString(PROJECT_CODE_DATA_KEY), getKey(),0,null));
dest.add(new ReviewItem("Kondisi Asset", mData.getString(REMARK_DATA_KEY), getKey(), 0, null));
}
#Override
public boolean isCompleted() {
return (!TextUtils.isEmpty(mData.getString(ASSET_TYPE_NAME_KEY)) &&
!TextUtils.isEmpty(mData.getString(ASSET_ID_DATA_KEY)) &&
!TextUtils.isEmpty(mData.getString(PROJECT_CODE_DATA_KEY)) &&
!TextUtils.isEmpty(mData.getString(REMARK_DATA_KEY)));
}
}
The first fragment:
public class AssetRegistrationInfoFragment extends Fragment {
private static final String ARG_KEY = "key";
private PageFragmentCallbacks mCallbacks;
private String mKey;
private AssetRegistrationInfoPage mPage;
private TextView mAssetID;
private AutoCompleteTextView mAssetTypeName, mProjectCode;
private TextView mRemark;
private Button mTakePicture;
static final int REQUEST_PICTURE_CAPTURE = 1;
private String pictureFilePath;
Bitmap bitmap;
ImageView mImgView;
ArrayList<String> projectCodes = new ArrayList<String>();
ArrayList<String> assetTypeNames = new ArrayList<String>();
public static AssetRegistrationInfoFragment create(String key) {
Bundle args = new Bundle();
args.putString(ARG_KEY, key);
AssetRegistrationInfoFragment fragment = new AssetRegistrationInfoFragment();
fragment.setArguments(args);
return fragment;
}
public AssetRegistrationInfoFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
mKey = args.getString(ARG_KEY);
mPage = (AssetRegistrationInfoPage) mCallbacks.onGetPage(mKey);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
boolean cancel = false;
mAssetTypeName.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1,
int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
mPage.getData().putString(AssetRegistrationInfoPage.ASSET_TYPE_NAME_KEY,
(editable != null) ? editable.toString() : null);
mPage.notifyDataChanged();
}
});
mAssetID.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1,
int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
mPage.getData().putString(AssetRegistrationInfoPage.ASSET_ID_DATA_KEY,
(editable != null) ? editable.toString() : null);
mPage.notifyDataChanged();
}
});
mProjectCode.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1,
int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
mPage.getData().putString(AssetRegistrationInfoPage.PROJECT_CODE_DATA_KEY,
(editable != null) ? editable.toString() : null);
mPage.notifyDataChanged();
}
});
mRemark.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1,
int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
mPage.getData().putString(AssetRegistrationInfoPage.REMARK_DATA_KEY,
(editable != null) ? editable.toString() : null);
mPage.notifyDataChanged();
}
});
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_page_asset_registration_info, container, false);
((TextView) view.findViewById(android.R.id.title)).setText(mPage.getTitle());
getAssetType();
mAssetTypeName = ((AutoCompleteTextView) view.findViewById(R.id.assetTypeName));
mAssetTypeName.setText(mPage.getData().getString(AssetRegistrationInfoPage.ASSET_TYPE_NAME_KEY));
ArrayAdapter<String> assetTypeNameAdapter = new ArrayAdapter<String>
(getActivity(), android.R.layout.simple_dropdown_item_1line, assetTypeNames);
mAssetTypeName.setAdapter(assetTypeNameAdapter);
mAssetID = ((TextView) view.findViewById(R.id.assetID));
mAssetID.setText(mPage.getData().getString(AssetRegistrationInfoPage.ASSET_ID_DATA_KEY));
getProjects();
mProjectCode = ((AutoCompleteTextView) view.findViewById(R.id.projectCode));
mProjectCode.setText(mPage.getData().getString(AssetRegistrationInfoPage.PROJECT_CODE_DATA_KEY));
mProjectCode.setThreshold(1);
ArrayAdapter<String> projectCodeAdapter = new ArrayAdapter<String>
(getActivity(), android.R.layout.simple_dropdown_item_1line, projectCodes);
mProjectCode.setAdapter(projectCodeAdapter);
mRemark = ((TextView) view.findViewById(R.id.remark));
mRemark.setText(mPage.getData().getString(AssetRegistrationInfoPage.REMARK_DATA_KEY));
return view;
}
private void getProjects() {
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
Call<List<Project>> call = apiService.getProjects("");
call.enqueue(new Callback<List<Project>>() {
#Override
public void onResponse(Call<List<Project>> call, Response<List<Project>> response) {
for (Project project : response.body()) {
projectCodes.add(project.getProjectCode());
}
}
#Override
public void onFailure(Call<List<Project>> call, Throwable t) {
Toast.makeText(getActivity(), "Unable to fetch Data " , Toast.LENGTH_LONG).show();
}
});
}
private void getAssetType() {
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
Call<List<AssetType>> call = apiService.getAssetTypes("");
call.enqueue(new Callback<List<AssetType>>() {
#Override
public void onResponse(Call<List<AssetType>> call, Response<List<AssetType>> response) {
for (AssetType assetType : response.body()) {
assetTypeNames.add(assetType.getName());
}
}
#Override
public void onFailure(Call<List<AssetType>> call, Throwable t) {
Toast.makeText(getActivity(), "Unable to fetch Data ", Toast.LENGTH_LONG).show();
}
});
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (!(activity instanceof PageFragmentCallbacks)) {
throw new ClassCastException("Activity must implement PageFragmentCallbacks");
}
mCallbacks = (PageFragmentCallbacks) activity;
}
#Override
public void onDetach() {
super.onDetach();
mCallbacks = null;
}
#Override
public void setMenuVisibility(boolean menuVisible) {
super.setMenuVisibility(menuVisible);
// In a future update to the support library, this should override setUserVisibleHint
// instead of setMenuVisibility.
if ( mAssetTypeName != null && mAssetID != null && mProjectCode != null && mRemark != null){
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(
Context.INPUT_METHOD_SERVICE);
if (!menuVisible) {
imm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
}
}
}
}
The second page
public class AssetRegConfirmationPage extends Page {
public static final String ASSET_TYPE_NAME_KEY = "assetTypeName";
public AssetRegConfirmationPage(ModelCallbacks callbacks, String title) {
super(callbacks, title);
}
#Override
public Fragment createFragment() {
return AssetRegConfirmationFragment.create(getKey());
}
#Override
public void getReviewItems(ArrayList<ReviewItem> dest) {
dest.add(new ReviewItem("Nama Asset", mData.getString(ASSET_TYPE_NAME_KEY), getKey(), 0, null));
}
}
The second fragment
public class AssetRegConfirmationFragment extends ListFragment implements ModelCallbacks {
private static final String ARG_KEY = "key";
private Callbacks mCallbacks;
private AbstractWizardModel mWizardModel;
private List<ReviewItem> mCurrentReviewItems;
private ReviewAdapter mReviewAdapter;
public AssetRegConfirmationFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mReviewAdapter = new ReviewAdapter();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_page, container, false);
TextView titleView = (TextView) rootView.findViewById(android.R.id.title);
titleView.setText(R.string.review);
titleView.setTextColor(getResources().getColor(R.color.colorPrimaryOld));
ListView listView = (ListView) rootView.findViewById(android.R.id.list);
setListAdapter(mReviewAdapter);
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
return rootView;
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (!(activity instanceof Callbacks)) {
throw new ClassCastException("Activity must implement fragment's callbacks");
}
mCallbacks = (Callbacks) activity;
mWizardModel = mCallbacks.onGetModel();
mWizardModel.registerListener(this);
onPageTreeChanged();
}
#Override
public void onPageTreeChanged() {
onPageDataChanged(null);
}
#Override
public void onDetach() {
super.onDetach();
mCallbacks = null;
mWizardModel.unregisterListener(this);
}
#Override
public void onPageDataChanged(Page changedPage) {
ArrayList<ReviewItem> reviewItems = new ArrayList<ReviewItem>();
for (Page page : mWizardModel.getCurrentPageSequence()) {
page.getReviewItems(reviewItems);
}
Collections.sort(reviewItems, new Comparator<ReviewItem>() {
#Override
public int compare(ReviewItem a, ReviewItem b) {
return a.getWeight() > b.getWeight() ? +1 : a.getWeight() < b.getWeight() ? -1 : 0;
}
});
mCurrentReviewItems = reviewItems;
if (mReviewAdapter != null) {
mReviewAdapter.notifyDataSetInvalidated();
}
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
mCallbacks.onEditScreenAfterReview(mCurrentReviewItems.get(position).getPageKey());
}
public interface Callbacks {
AbstractWizardModel onGetModel();
void onEditScreenAfterReview(String pageKey);
}
private class ReviewAdapter extends BaseAdapter {
#Override
public boolean hasStableIds() {
return true;
}
#Override
public int getItemViewType(int position) {
return 0;
}
#Override
public int getViewTypeCount() {
return 1;
}
#Override
public boolean areAllItemsEnabled() {
return true;
}
#Override
public Object getItem(int position) {
return mCurrentReviewItems.get(position);
}
#Override
public long getItemId(int position) {
return mCurrentReviewItems.get(position).hashCode();
}
#Override
public View getView(int position, View view, ViewGroup container) {
LayoutInflater inflater = LayoutInflater.from(getActivity());
View rootView = inflater.inflate(R.layout.list_item_review, container, false);
ReviewItem reviewItem = mCurrentReviewItems.get(position);
String value = reviewItem.getDisplayValue();
if (TextUtils.isEmpty(value)) {
value = "(None)";
}
((TextView) rootView.findViewById(android.R.id.text1)).setText(reviewItem.getTitle());
((TextView) rootView.findViewById(android.R.id.text2)).setText(value);
return rootView;
}
#Override
public int getCount() {
return mCurrentReviewItems.size();
}
}
public static AssetRegConfirmationFragment create(String key) {
Bundle args = new Bundle();
args.putString(ARG_KEY, key);
AssetRegConfirmationFragment fragment = new AssetRegConfirmationFragment();
fragment.setArguments(args);
return fragment;
}
}
I have no idea of what should I do to make this work.
Here is the Page source code:
public abstract class Page implements PageTreeNode {
/**
* The key into {#link #getData()} used for wizards with simple (single) values.
*/
public static final String SIMPLE_DATA_KEY = "_";
protected ModelCallbacks mCallbacks;
/**
* Current wizard values/selections.
*/
protected Bundle mData = new Bundle();
protected String mTitle;
protected boolean mRequired = false;
protected String mParentKey;
protected Page(ModelCallbacks callbacks, String title) {
mCallbacks = callbacks;
mTitle = title;
}
public Bundle getData() {
return mData;
}
public String getTitle() {
return mTitle;
}
public boolean isRequired() {
return mRequired;
}
void setParentKey(String parentKey) {
mParentKey = parentKey;
}
#Override
public Page findByKey(String key) {
return getKey().equals(key) ? this : null;
}
#Override
public void flattenCurrentPageSequence(ArrayList<Page> dest) {
dest.add(this);
}
public abstract Fragment createFragment();
public String getKey() {
return (mParentKey != null) ? mParentKey + ":" + mTitle : mTitle;
}
public abstract void getReviewItems(ArrayList<ReviewItem> dest);
public boolean isCompleted() {
return true;
}
public Bitmap getPicture() {
return mData.getParcelable(getKey() + "_" + getTitle().trim());
}
public void resetData(Bundle data) {
mData = data;
notifyDataChanged();
}
public void notifyDataChanged() {
mCallbacks.onPageDataChanged(this);
}
public Page setRequired(boolean required) {
mRequired = required;
return this;
}
}
Look at this code in second fragment:
if (!(activity instanceof Callbacks)) {
throw new ClassCastException("Activity must implement fragment's callbacks");
}
Your activity where you using second fragment should implement Callbacks interface, like:
class YourActivity implements Callbacks {
}
Related
I already implemented onClick now I want to add onLongClick , I searched non of the solutions matched my case, because my adapter is setup differently
Adapter
public class StudioAdapter extends RecyclerView.Adapter<StudioAdapter.StudioViewHolder> {
public interface OnItemClickListener {
void onItemClick(int item);
}
private List<String> StudioLogoPaths;
private OnItemClickListener listener;
public StudioAdapter(List<String> StudioLogoPaths, OnItemClickListener listener) {
this.StudioLogoPaths = (List<String>) StudioLogoPaths;
this.listener = listener;
}
#Override
public StudioAdapter.StudioViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.studio_logo, parent, false);
StudioViewHolder vh = new StudioViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder( StudioAdapter.StudioViewHolder vh, int position) {
final String path = StudioLogoPaths.get(position);
Glide.with(vh.itemView.getContext()).load(path).into(vh.logoImage);
String basepath = "/data/user/0/org.courville.nova/app_scraper_studiologos/";
String extension = ".png";
final String clicked_studioname = path.replace(basepath, "").replace(extension, "");
final int Position = position;
vh.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
listener.onItemClick(Position);
Toast.makeText(vh.itemView.getContext(), clicked_studioname, Toast.LENGTH_SHORT).show();
}
});
}
#Override
public int getItemCount() {
return StudioLogoPaths.size();
}
public class StudioViewHolder extends RecyclerView.ViewHolder {
protected ImageView logoImage;
public StudioViewHolder(View itemView) {
super(itemView);
logoImage = itemView.findViewById(R.id.studio_logo);
}
}
}
my Fragment
StudioAdapter.OnItemClickListener studioLogoCallback = new StudioAdapter.OnItemClickListener() {
#Override
public void onItemClick(int item) {
Glide.with(mContext).clear(mLogo);
Glide.with(mContext).load(tags.getStudioLogosLargeFileF().get(item))
.fitCenter().into(mLogo);
List<ScraperImage> scraperImage = tags.getStudioLogos();
ScraperImage clickedImage = (ScraperImage) scraperImage.get(item);
new VideoInfoActivityFragment.ClearLogoSaver(mContext, new VideoInfoActivityFragment()).execute(clickedImage);
}
};
final StudioAdapter studioAdapter = new StudioAdapter(StudioLogoPaths,studioLogoCallback);
studios.setAdapter(studioAdapter);
You need to add a 2nd method to your interface to represent the long click event. Then, within onBindViewHolder, add vh.itemView.setOnLongClickListener(...) in which you call that 2nd method.
Edit:
Your interface should now look like this:
public interface OnItemClickListener {
void onItemClick(int item);
void onItemLongClick(int item);
}
I solved it like this:
Adapter
public class StudioAdapter extends RecyclerView.Adapter<StudioAdapter.StudioViewHolder> {
public interface OnItemClickListener {
void onItemClick(int item);
void onItemLongClick(int position);
}
private List<String> StudioLogoPaths;
private OnItemClickListener listener;
public StudioAdapter(List<String> StudioLogoPaths, OnItemClickListener listener) {
this.StudioLogoPaths = (List<String>) StudioLogoPaths;
this.listener = listener;
}
#Override
public StudioAdapter.StudioViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.studio_logo, parent, false);
StudioViewHolder vh = new StudioViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder( StudioAdapter.StudioViewHolder vh, int position) {
final String path = StudioLogoPaths.get(position);
Glide.with(vh.itemView.getContext()).load(path).into(vh.logoImage);
String basepath = "/data/user/0/org.courville.nova/app_scraper_studiologos/";
String extension = ".png";
final String clicked_studioname = path.replace(basepath, "").replace(extension, "");
final int Position = position;
vh.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
listener.onItemClick(Position);
Toast.makeText(vh.itemView.getContext(), clicked_studioname, Toast.LENGTH_SHORT).show();
}
});
vh.itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
listener.onItemLongClick(Position);
return false;
}
});
}
#Override
public int getItemCount() {
return StudioLogoPaths.size();
}
public class StudioViewHolder extends RecyclerView.ViewHolder {
protected ImageView logoImage;
public StudioViewHolder(View itemView) {
super(itemView);
logoImage = itemView.findViewById(R.id.studio_logo);
}
}
}
Fragment
StudioAdapter.OnItemClickListener studioLogoCallback = new StudioAdapter.OnItemClickListener() {
#Override
public void onItemClick(int item) {
}
#Override
public void onItemLongClick(int position) {
Glide.with(mContext).clear(mLogo);
Glide.with(mContext).load(tags.getStudioLogosLargeFileF().get(position))
.fitCenter().into(mLogo);
ScraperImage clickedImage = (ScraperImage) scraperImage.get(position);
new VideoInfoActivityFragment.ClearLogoSaver(mContext, new VideoInfoActivityFragment()).execute(clickedImage);
}
};
I Am Trying to Implement RecyclerView With EditText. First I Am Fetching Members List From Database And then for each member I want to get value from user input(EditText).
But when I submit data, values for the members are getting shuffled.
I Am Using TextWatcher Class, When Text Get changed it adds value in the model class.
Values are getting shuffled when I scroll the RecyclerView.
I tried all the solutions on the stack overflow but none of it worked
following is my code:
For Fetching the data:
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
ProgressBar progressBar;
LinearLayoutManager manager;
String URL = "members_fetch.php?club_id=98";
List<MemberListDetails> memberListDetailsList = new ArrayList<>();
private LinearLayoutManager layoutManager;
MemberListDetails memberListDetails;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = findViewById(R.id.progress);
Button button = findViewById(R.id.button);
recyclerView = findViewById(R.id.my_recycler_view);
manager = new LinearLayoutManager(this);
initRecyclerView();
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String z = ((Adapter) recyclerView.getAdapter()).getValue().toString();
Log.wtf("aaa", z);
}
});
getMembersDetails();
}
private void initRecyclerView() {
layoutManager = new LinearLayoutManager(this);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(layoutManager);
}
private void getMembersDetails() {
final ProgressDialog pd = new ProgressDialog(this);
pd.setMessage("Loading Members Details");
pd.show();
pd.setCancelable(false);
pd.setCanceledOnTouchOutside(false);
RequestQueue queue = Volley.newRequestQueue(MainActivity.this);
StringRequest stringRequest = new StringRequest(Request.Method.GET, URL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
pd.dismiss();
try {
JSONArray jsonArray = new JSONArray(response);
for (int i = 0; i < jsonArray.length(); i++) {
Log.d("ssdf", "fsdf" + response);
JSONObject o = jsonArray.getJSONObject(i);
memberListDetails = new MemberListDetails();
memberListDetails.setStatus(o.getString("status"));
memberListDetails.setMembership_id(o.getString("membership_id"));
memberListDetails.setFirst_name(o.getString("first_name"));
memberListDetails.setMiddle_name(o.getString("middle_name"));
memberListDetails.setLast_name(o.getString("last_name"));
memberListDetails.setClub_post(o.getString("club_post"));
memberListDetails.setDistrict_post(o.getString("district_post"));
memberListDetails.setGender(o.getString("gender"));
memberListDetails.setPost_name(o.getString("post_name"));
memberListDetailsList.add(memberListDetails);
Log.d("hhhhh", "xxxx" + memberListDetailsList);
}
recyclerView.setAdapter(new Adapter(memberListDetailsList, MainActivity.this));
} catch (Exception e) {
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MainActivity.this, error.getMessage(), Toast.LENGTH_SHORT).show();
Log.d("errorMsg", "dddd" + error.getMessage());
pd.dismiss();
}
});
queue.add(stringRequest);
}
}
For Adapter Class :
public class Adapter extends RecyclerView.Adapter<Adapter.VHolder> {
private List<MemberListDetails> data;
Context context;
EditText text;
Integer pos;
public Adapter(List<MemberListDetails> data, Context context) {
this.data = data;
this.context = context;
}
#NonNull
#Override
public Adapter.VHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.item, viewGroup, false);
return new VHolder(view);
}
#Override
public int getItemCount() {
return data.size();
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}
public List<MemberListDetails> getItems() {
return data;
}
#Override
public void onBindViewHolder(#NonNull Adapter.VHolder vHolder, int i) {
vHolder.setIsRecyclable(false);
vHolder.textView.setText(data.get(i).getFirst_name());
text = vHolder.editText;
pos = i;
text.setText(data.get(i).getValue());
text.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// text.setError(null);
data.get(pos).setValue(s.toString());
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
// text.setError(null);
data.get(pos).setValue(s.toString());
}
});
}
public class VHolder extends RecyclerView.ViewHolder {
TextView textView;
EditText editText;
public VHolder(View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.tv_textView);
editText = itemView.findViewById(R.id.editText2);
}
}
String getValue() {
StringBuffer x = new StringBuffer();
for (MemberListDetails a : data) {
x.append(a.getValue()+",");
}
return x.substring(0,x.length()-1);
}
}
I think you need to remove global edit text and position. Also, add text watcher in holder class. Please check below code. it may help you.
public class Adapter extends RecyclerView.Adapter<Adapter.VHolder> {
private List<MemberListDetails> data;
Context context;
public Adapter(List<MemberListDetails> data, Context context) {
this.data = data;
this.context = context;
}
#NonNull
#Override
public Adapter.VHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.item, viewGroup, false);
return new VHolder(view);
}
#Override
public int getItemCount() {
return data.size();
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}
public List<MemberListDetails> getItems() {
return data;
}
#Override
public void onBindViewHolder(#NonNull Adapter.VHolder vHolder, int i) {
vHolder.setIsRecyclable(false);
vHolder.textView.setText(data.get(i).getFirst_name());
vHolder.editText.removeTextChangedListener(vHolder.textWatcher);
vHolder.editText.setText(data.get(i).getValue());
vHolder.editText.addTextChangedListener(vHolder.textWatcher);
}
public class VHolder extends RecyclerView.ViewHolder {
TextView textView;
EditText editText;
TextWatcher textWatcher;
public VHolder(View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.tv_textView);
editText = itemView.findViewById(R.id.editText2);
textWatcher = new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
// text.setError(null);
data.get(getAdapterPosition()).setValue(s.toString());
}
};
}
}
String getValue() {
StringBuffer x = new StringBuffer();
for (MemberListDetails a : data) {
x.append(a.getValue()+",");
}
return x.substring(0,x.length()-1);
}
Here is the solution. It may contain some error because I am not able to compile if due unavailable of resources like xml file and Model class But it definitely works for you. Because I have implemented the same in my project and working fine
public class Adapter extends RecyclerView.Adapter<Adapter.VHolder> {
private List<MemberListDetails> data;
Context context;
Integer pos;
public Adapter(List<MemberListDetails> data, Context context) {
this.data = data;
this.context = context;
}
#NonNull
#Override
public Adapter.VHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.item, viewGroup, false);
return new VHolder(view);
}
#Override
public int getItemCount() {
return data.size();
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}
public List<String> getItems() {
return data;
}
#Override
public void onBindViewHolder(#NonNull Adapter.VHolder vHolder, int i) {
vHolder.setIsRecyclable(false);
vHolder.textView.setText(data.get(i).getFirst_name());
pos = i;
vHolder.myCustomEditTextListener.updatePosition(vHolder.getAdapterPosition());
vHolder.editText.setText(data.get(vHolder.getAdapterPosition()));
}
public class VHolder extends RecyclerView.ViewHolder {
TextView textView;
EditText editText;
public MyCustomEditTextListener myCustomEditTextListener;
public VHolder(View itemView, MyCustomEditTextListener myCustomEditTextListener) {
super(itemView);
textView = itemView.findViewById(R.id.tv_textView);
editText = itemView.findViewById(R.id.editText2);
this.editText.addTextChangedListener(myCustomEditTextListener);
}
}
String getValue() {
StringBuffer x = new StringBuffer();
for (MemberListDetails a : data) {
x.append(a.getValue() + ",");
}
return x.substring(0, x.length() - 1);
}
private class MyCustomEditTextListener implements TextWatcher {
private int position;
public void updatePosition(int position) {
this.position = position;
}
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
// no op
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
data.set(position, charSequence.toString());
}
#Override
public void afterTextChanged(Editable editable) {
// no op
}
}
}
I have a problem with my code, when i do a single or double tap on item both onDoubleTap and onSingleTapConfirmed are actived while i dont have problem with onLongClick.
In my activity:
mRecyclerView.addOnItemTouchListener(new RecyclerTouchListener(getContext(), mRecyclerView, new RecyclerTouchListener.ClickListener() {
#Override
public void onSingleTapConfirmed(View view, int position) {}
#Override
public void onDoubleTap(View view, int position){}
#Override
public void onLongClick(View view, int position) {}
}));
In my custom listener class:
public class RecyclerTouchListener implements recyclerView.OnItemTouchListener{
private GestureDetector gestureDetector;
private ClickListener clickListener;
public RecyclerTouchListener(Context context, final RecyclerView recyclerView, final ClickListener clickListener) {
this.clickListener = clickListener;
gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
return true;
}
#Override
public void onLongPress(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null) {
clickListener.onLongClick(child, recyclerView.getChildPosition(child));
}
}
#Override
public boolean onDoubleTap(MotionEvent e) {
return true;
}
});
}
#Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child = rv.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
clickListener.onSingleTapConfirmed(child, rv.getChildPosition(child));
}
return false;
}
public interface ClickListener {
void onSingleTapConfirmed(View view, int position);
void onDoubleTap(View view, int position);
void onLongClick(View view, int position);
}}
add this listener as OnDoubleClickListener.java:
public abstract class OnDoubleClickListener implements View.OnClickListener {
private final int doubleClickTimeout;
private Handler handler;
private long firstClickTime;
public OnDoubleClickListener() {
doubleClickTimeout = ViewConfiguration.getDoubleTapTimeout();
firstClickTime = 0L;
handler = new Handler(Looper.getMainLooper());
}
#Override
public void onClick(final View v) {
long now = System.currentTimeMillis();
if (now - firstClickTime < doubleClickTimeout) {
handler.removeCallbacksAndMessages(null);
firstClickTime = 0L;
onDoubleClick(v);
} else {
firstClickTime = now;
handler.postDelayed(new Runnable() {
#Override
public void run() {
onSingleClick(v);
firstClickTime = 0L;
}
}, doubleClickTimeout);
}
}
public abstract void onDoubleClick(View v);
public abstract void onSingleClick(View v);
public void reset() {
handler.removeCallbacksAndMessages(null);
}
}
and then add ItemClickSupport.java
public class ItemClickSupport {
private final RecyclerView mRecyclerView;
private OnItemClickListener mOnItemClickListener;
private OnDoubleClickListener mOnDoubleClickListener = new OnDoubleClickListener() {
#Override
public void onDoubleClick(View v) {
if (mOnItemClickListener != null) {
RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
mOnItemClickListener.onItemDoubleClicked(mRecyclerView, holder.getAdapterPosition(), v);
}
}
#Override
public void onSingleClick(View v) {
if (mOnItemClickListener != null) {
RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
mOnItemClickListener.onItemClicked(mRecyclerView, holder.getAdapterPosition(), v);
}
}
};
private RecyclerView.OnChildAttachStateChangeListener mAttachListener
= new RecyclerView.OnChildAttachStateChangeListener() {
#Override
public void onChildViewAttachedToWindow(View view) {
if (mOnItemClickListener != null) {
view.setOnClickListener(mOnDoubleClickListener);
}
}
#Override
public void onChildViewDetachedFromWindow(View view) {
}
};
private ItemClickSupport(RecyclerView recyclerView) {
mRecyclerView = recyclerView;
mRecyclerView.setTag(R.id.item_click_support, this);
mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener);
}
public static ItemClickSupport addTo(RecyclerView view) {
ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
if (support == null) {
support = new ItemClickSupport(view);
}
return support;
}
public static ItemClickSupport removeFrom(RecyclerView view) {
ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
if (support != null) {
support.detach(view);
}
return support;
}
public ItemClickSupport setOnItemClickListener(OnItemClickListener listener) {
mOnItemClickListener = listener;
return this;
}
private void detach(RecyclerView view) {
view.removeOnChildAttachStateChangeListener(mAttachListener);
view.setTag(R.id.item_click_support, null);
}
public interface OnItemClickListener {
void onItemClicked(RecyclerView recyclerView, int position, View v);
void onItemDoubleClicked(RecyclerView recyclerView, int position, View v);
}
}
and use it :
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new GridLayoutManager(getActivity(),
2, GridLayoutManager.VERTICAL, false));
// Make sure your recyler view adapter implements getItemAt(position), which return the item from the dataset placed at position
// in this case I use getProductId() from my POJO Product class
ItemClickSupport.addTo(mRecyclerView)
.setOnItemClickListener(new ItemClickSupport.OnItemClickListener() {
#Override
public void onItemClicked(RecyclerView recyclerView, int position, View v) {
Log.d("ITEM CLICK", "Item single clicked " + mRecyclerViewAdapter.getItemAt(position).getProductId());
}
#Override
public void onItemDoubleClicked(RecyclerView recyclerView, int position, View v) {
Log.d("ITEM CLICK", "Item double clicked " + mRecyclerViewAdapter.getItemAt(position).getProductId());
}
});
source
or check this gist
I am learning new components and try to use LiveData with DataBinding and ModelView. I have a problem with showing items on recyclerview (updating UI). Here is my ModelView:
public class PlacesViewModel extends ViewModel {
private MutableLiveData<List<Place>> placeList;
private Repository repository;
public PlacesViewModel() {
repository = Repository.getInstance();
}
public LiveData<List<Place>> getPlaceList() {
if (placeList == null) {
placeList = new MutableLiveData<List<Place>>();
getPlaces();
}
return placeList;
}
private void getPlaces() {
repository.getLocationsFromBackend(new DataSource.GetLocationsCallback() {
#Override
public void onSuccess(MutableLiveData<List<Place>> body) {
if (body != null) {
placeList = body;
} else {
placeList = new MutableLiveData<>();
}
}
#Override
public void onError(int code) {
}
#Override
public void onUnknownError() {
}
#Override
public void onNoInternet() {
}
#Override
public void onNoServer() {
}
#Override
public void onAlreadyPairedError() {
}
#Override
public void onNoCustomerError() {
}
#Override
public void onLoadIndicator(boolean active) {
}
#Override
public void reAuthenticate() {
}
});
}
The problem comes, when I launch the app, screen is "empty". But, when I am in debug mode and in line getPlaceList(), I can switch to background thread to execute api call using retrofit. Only than it works...
Here is my Repository singleton with method:
public class Repository implements DataSource {
private static Repository INSTANCE;
private ApiService service = new RetrofitFactory().getService();
private static final int RESPONSE_OK = 0;
private final MutableLiveData<List<Place>> data = new MutableLiveData<>();
public synchronized static Repository getInstance() {
if (INSTANCE==null) {
INSTANCE=new Repository();
}
return(INSTANCE);
}
private Repository() {
}
private <T extends BaseResponse> void handleActualResult(BaseLoadCallback<T> dataSource,
MutableLiveData<List<Place>> actualResult) {
final int resultCode = 0;
switch (resultCode) {
case RESPONSE_OK:
dataSource.onSuccess(actualResult);
break;
default:
dataSource.onError(resultCode);
break;
}
}
#Override
public void getLocationsFromBackend(GetLocationsCallback presener) {
final SecurityRequest request = new SecurityRequest();
service.getPlaces(request).enqueue(new Callback<GetPlacesResponse>() {
#Override
public void onResponse(#NonNull Call<GetPlacesResponse> call, #NonNull Response<GetPlacesResponse> response) {
if (response.isSuccessful()) {
if (response.body() != null) {
data.postValue(response.body().getLokali());
handleActualResult(presener, data);
}
}
}
#Override
public void onFailure(#NonNull Call<GetPlacesResponse> call, #NonNull Throwable t) {
Log.d("Error: ", t.getMessage());
}
});
}
#Override
public List<Place> getLocations() {
return null;
}
}
It goes to onResposne and than back to getPlaceList() and returns filled list with objects. Here is how I make an instance of viewmodel and observe LiveData object:
public class LocationFragment extends Fragment {
private PlacesViewModel placesViewModel;
private RecyclerView recyclerView;
private PlaceCustomAdapter customAdapter;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
recyclerView = view.findViewById(R.id.recyclerViewId);
placesViewModel = ViewModelProviders.of(LocationFragment.this).get(PlacesViewModel.class);
customAdapter = new PlaceCustomAdapter(getLayoutInflater());
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
recyclerView.setHasFixedSize(false);
placesViewModel.getPlaceList().observe(this, places -> {
customAdapter.setList(places);
recyclerView.setAdapter(customAdapter);
});
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return(inflater.inflate(R.layout.activity_main, container, false));
}
Here is also my adapter:
public class PlaceCustomAdapter extends RecyclerView.Adapter<PlaceCustomAdapter.CustomLocationViewHolder> {
private LayoutInflater layoutInflater;
private List<Place> placeList;
public PlaceCustomAdapter(LayoutInflater layoutInflater) {
this.layoutInflater = layoutInflater;
}
#NonNull
#Override
public PlaceCustomAdapter.CustomLocationViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
ViewDataBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.single_item_row_recycler_view, parent, false);
return new PlaceCustomAdapter.CustomLocationViewHolder(binding);
}
#Override
public void onBindViewHolder(#NonNull PlaceCustomAdapter.CustomLocationViewHolder holder, int position) {
Place p = placeList.get(position);
holder.bind(p);
}
void setList(List<Place> placeList) {
this.placeList = placeList;
notifyDataSetChanged();
}
#Override
public int getItemCount() {
return(placeList == null ? 0 : placeList.size());
}
public class CustomLocationViewHolder extends RecyclerView.ViewHolder {
private final ViewDataBinding binding;
public CustomLocationViewHolder(ViewDataBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
public void bind(Object obj) {
binding.setVariable(BR.model, obj);
binding.executePendingBindings();
}
}
So, it does not crash, only recycler is empty...If you need any extra explanation, just ask.
I would appreciate any help. Thanx
I just figured it out what was wrong. I was calling a method handleActualResult(presener, data);
in wrong place. Instead in onSuccess I put it out to handle response...
#Override
public void getLocationsFromBackend(GetLocationsCallback presener) {
final SecurityRequest request = new SecurityRequest();
service.getPlaces(request).enqueue(new Callback<GetPlacesResponse>() {
#Override
public void onResponse(#NonNull Call<GetPlacesResponse> call, #NonNull Response<GetPlacesResponse> response) {
if (response.isSuccessful()) {
if (response != null) {
data.postValue(response.body().getLokali());
} else {
data = new MutableLiveData<>();
}
}
}
#Override
public void onFailure(#NonNull Call<GetPlacesResponse> call, #NonNull Throwable t) {
Log.d("Error: ", t.getMessage());
}
});
handleActualResult(presener, data);
}
If anyone counter the same problem...Enjoy!
I am trying to open a url link when I click on a list item in a recyclerview but I keep getting a NullPointerException. I am using a ViewPager, I don't know if this is the cause of the exception, maybe I'm doing something wrong. Please check out my code and logcat below.
This is my adapter:
public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.NewsHolder> {
private ArrayList<News> mNews = new ArrayList<>();
private static ClickListener clickListener;
public NewsAdapter(ArrayList<News> news) {
mNews = news;
}
private static String timeConverter(String inputTime) {
long startTime = 0;
SimpleDateFormat simpleDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
simpleDate.setTimeZone(TimeZone.getTimeZone("GMT"));
try {
Date date = simpleDate.parse(inputTime);
startTime = date.getTime();
} catch (ParseException e) {
e.printStackTrace();
}
long currentTime = System.currentTimeMillis();
long end = currentTime - startTime;
long seconds = TimeUnit.MILLISECONDS.toSeconds(end);
long minutes = TimeUnit.SECONDS.toMinutes(seconds);
long hours = TimeUnit.MINUTES.toHours(minutes);
if (minutes > 59) {
return hours + "h";
}else if (seconds > 59) {
return minutes + "m";
}else {
return seconds + "s";
}
}
#Override
public NewsHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_view, parent, false);
return new NewsHolder(view);
}
#Override
public void onBindViewHolder(NewsHolder holder, int position) {
String imagePath = mNews.get(position).getImageUrl();
Picasso.with(holder.mImageView.getContext()).load(imagePath).into(holder.mImageView);
holder.mNewsTextView.setText(mNews.get(position).getNews());
holder.mTimeStampTextView.setText(timeConverter(mNews.get(position).getTime()));
}
#Override
public int getItemCount() {
return mNews.size();
}
// NewsHolder class that extends the ViewHolder
public static class NewsHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private ImageView mImageView;
private TextView mNewsTextView;
private TextView mTimeStampTextView;
// Setting the views
public NewsHolder(View itemView) {
super(itemView);
mImageView = (ImageView) itemView.findViewById(R.id.simple_imageView);
mNewsTextView = (TextView) itemView.findViewById(R.id.news_tv);
mTimeStampTextView = (TextView) itemView.findViewById(R.id.time_tv);
}
#Override
public void onClick(View view) {
clickListener.onItemClick(getAdapterPosition(), view);
}
}
public void setOnItemClickListener(ClickListener listener) {
NewsAdapter.clickListener = listener;
}
public interface ClickListener {
void onItemClick(int position, View v);
}
}
This is one of my ViewPager fragments:
public class TechFragment extends Fragment {
private SwipeRefreshLayout mSwipeRefreshLayout;
private TextView mErrorMessage;
private NewsAdapter mNewsAdapter;
ArrayList<News> news;
NetworkInfo info;
// The Loader takes in a bundle
Bundle sourceBundle = new Bundle();
private final String LOG_TAG = MainActivity.class.getSimpleName();
private static final String TECH_NEWS_QUERY_URL = "query";
private static final String TECH_NEWS_SOURCE = "techcrunch";
private static final String TECH_SOURCE_CATEGORY = "latest";
private static final int TECH_NEWS_LOADER = 22;
private RecyclerView mRecyclerView;
public TechFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_news, container, false);
mErrorMessage = (TextView) view.findViewById(R.id.tv_error_message);
mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view_main);
mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipeRefresh);
getActivity().getSupportLoaderManager().initLoader(TECH_NEWS_LOADER, sourceBundle, new NewsDataLoader());
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
Log.v(LOG_TAG, "Refreshing");
restartLoader();
mSwipeRefreshLayout.setColorSchemeResources(
R.color.colorPrimary,
R.color.colorPrimaryDark);
}
});
return view;
}
private boolean isConnected() {
ConnectivityManager cm = (ConnectivityManager) getActivity()
.getSystemService(CONNECTIVITY_SERVICE);
info = cm.getActiveNetworkInfo();
return info != null && info.isConnectedOrConnecting();
}
private int anyRandomInt(Random random) {
return random.nextInt();
}
private void restartLoader() {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
URL techNewsUrl = NetworkUtils.buildUrl(TECH_NEWS_SOURCE, TECH_SOURCE_CATEGORY);
sourceBundle.putString(TECH_NEWS_QUERY_URL, techNewsUrl.toString());
Random random = new Random();
int uniqueId = anyRandomInt(random); //Generates a new ID for each loader call;
LoaderManager loaderManager = getActivity().getSupportLoaderManager();
if (loaderManager.getLoader(TECH_NEWS_LOADER) == null) {
loaderManager.initLoader(uniqueId, sourceBundle, new NewsDataLoader());
} else {
loaderManager.restartLoader(TECH_NEWS_LOADER, sourceBundle, new
NewsDataLoader());
}
}
}, 5000);
mSwipeRefreshLayout.setRefreshing(false);
Log.v(LOG_TAG, "Finished refreshing");
}
private void showErrorScreen() {
mErrorMessage.setVisibility(View.VISIBLE);
mRecyclerView.setVisibility(View.INVISIBLE);
mErrorMessage.setText(getString(R.string.internet_error));
}
public class NewsDataLoader implements LoaderManager.LoaderCallbacks<ArrayList<News>> {
#Override
public Loader<ArrayList<News>> onCreateLoader(int id, final Bundle args) {
if (isConnected()) {
mErrorMessage.setVisibility(View.INVISIBLE);
mRecyclerView.setVisibility(View.VISIBLE);
return new AsyncTaskLoader<ArrayList<News>>(getActivity()) {
ArrayList<News> mNewsData;
#Override
protected void onStartLoading() {
super.onStartLoading();
if (mNewsData != null) {
deliverResult(mNewsData);
} else {
forceLoad();
mSwipeRefreshLayout.setRefreshing(true);
}
}
#Override
public ArrayList<News> loadInBackground() {
try {
ArrayList<News> news = NetworkUtils.parseJSON(TECH_NEWS_SOURCE, TECH_SOURCE_CATEGORY);
return news;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public void deliverResult(ArrayList<News> data) {
mNewsData = data;
super.deliverResult(data);
}
};
} else {
showErrorScreen();
return null;
}
}
#Override
public void onLoadFinished(Loader<ArrayList<News>> loader, final ArrayList<News> data) {
mSwipeRefreshLayout.setRefreshing(false);
if (null == data) {
showErrorScreen();
} else {
mErrorMessage.setVisibility(View.INVISIBLE);
mRecyclerView.setVisibility(View.VISIBLE);
if (news != null) {
news.clear();
news.addAll(data);
mNewsAdapter = new NewsAdapter(news);
mRecyclerView.setAdapter(mNewsAdapter);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
mNewsAdapter.notifyDataSetChanged();
} else {
news = data;
}
}
mNewsAdapter.setOnItemClickListener(new NewsAdapter.ClickListener() {
#Override
public void onItemClick(int position, View v) {
News currentNews = news.get(position);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(currentNews.getUrl()));
if (intent.resolveActivity(getActivity().getPackageManager()) != null){
startActivity(intent);
}
}
});
}
#Override
public void onLoaderReset(Loader<ArrayList<News>> loader) {
}
}
}
And this is my error:
06-13 12:11:38.667 3890-3890/com.ire.blogbot E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.ire.blogbot, PID: 3890
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.ire.blogbot.adapter.NewsAdapter.setOnItemClickListener(com.ire.blogbot.adapter.NewsAdapter$ClickListener)' on a null object reference
at com.ire.blogbot.fragments.TechFragment$NewsDataLoader.onLoadFinished(TechFragment.java:192)
at com.ire.blogbot.fragments.TechFragment$NewsDataLoader.onLoadFinished(TechFragment.java:131)
at android.support.v4.app.LoaderManagerImpl$LoaderInfo.callOnLoadFinished(LoaderManager.java:476)
at android.support.v4.app.LoaderManagerImpl$LoaderInfo.onLoadComplete(LoaderManager.java:444)
at android.support.v4.content.Loader.deliverResult(Loader.java:126)
at com.ire.blogbot.fragments.TechFragment$NewsDataLoader$1.deliverResult(TechFragment.java:164)
at com.ire.blogbot.fragments.TechFragment$NewsDataLoader$1.deliverResult(TechFragment.java:137)
at android.support.v4.content.AsyncTaskLoader.dispatchOnLoadComplete(AsyncTaskLoader.java:252)
at android.support.v4.content.AsyncTaskLoader$LoadTask.onPostExecute(AsyncTaskLoader.java:80)
at android.support.v4.content.ModernAsyncTask.finish(ModernAsyncTask.java:485)
at android.support.v4.content.ModernAsyncTask$InternalHandler.handleMessage(ModernAsyncTask.java:502)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Try this code, it is working
recyclerView.addOnItemTouchListener(
new RecyclerItemClickListener(getActivity(), new RecyclerItemClickListener.OnItemClickListener() {
#Override public void onItemClick(View view, int position) {
// on click
}
})
);
RecyclerItemClickListener Class
public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
private OnItemClickListener mListener;
public interface OnItemClickListener {
public void onItemClick(View view, int position);
}
GestureDetector mGestureDetector;
public RecyclerItemClickListener(Context context, OnItemClickListener listener) {
mListener = listener;
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
});
}
#Override
public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
View childView = view.findChildViewUnder(e.getX(), e.getY());
if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
mListener.onItemClick(childView, view.getChildAdapterPosition(childView));
}
return false;
}
#Override
public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) {
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}}
Move
mNewsAdapter.setOnItemClickListener(new NewsAdapter.ClickListener() {
#Override
public void onItemClick(int position, View v) {
News currentNews = news.get(position);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(currentNews.getUrl()));
if (intent.resolveActivity(getActivity().getPackageManager()) != null){
startActivity(intent);
}
}
});
after
mNewsAdapter = new NewsAdapter(news);