So, I've been using the Google's Friendlyeats example as guide. I changed it a bit in order to use Butterknife but had issues when trying to open a single doc (fragment) and show its content in the following activity.
I'm using a recyclerview to show the summarize data and then I want to show the full individual data on an activity. It's really not that much info, just four textviews.
Because of this, I decided to stick to the original example as much as I could to see what was up. Still same error. I can open the following activity but no data is being displayed.
I'm already three months behind lmao. please help!
here's the code:
MessageAdapter.java
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
holder.bind(getSnapshot(position), mListener);
}
static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
super(itemView);
headerView = itemView.findViewById(R.id.message_item_header);
senderView = itemView.findViewById(R.id.message_item_sender);
dateView = itemView.findViewById(R.id.message_item_date);
imageView = itemView.findViewById(R.id.message_item_image);
actualMessageView = itemView.findViewById(R.id.actual_message);
}
public void bind(final DocumentSnapshot snapshot,
final OnMessageSelectedListener listener) {
Messages messages = snapshot.toObject(Messages.class);
imageView.setImageResource(R.drawable.logo_app_off);
headerView.setText(messages.getHeader());
senderView.setText(messages.getSender());
actualMessageView.setText(messages.getMessage());
dateView.setText(messages.getDate());
itemView.setOnClickListener(v -> {
if (listener != null) {
listener.onMessageSelectedListener(snapshot);
}
});
}
}
}
HomeFragment.java
#Override
public void onMessageSelectedListener(DocumentSnapshot message) {
Intent intent = new Intent(getActivity(), MessageDetailActivity.class);
intent.putExtra(KEY_MESSAGE_ID, message.getId());
startActivity(intent);
}
private void initFirestore() {
mFirestore = FirebaseFirestore.getInstance();
mQuery = mFirestore.collection("messages")
.orderBy("date", Query.Direction.DESCENDING)
.limit(LIMIT);
}
private void initRecyclerView() {
if (mQuery == null) {
Log.w(TAG, "No query, not initializing RecyclerView");
}
mAdapter = new MessageAdapter(mQuery, this) {
#Override
protected void onDataChanged() {
if (getItemCount() == 0) {
mMessagesRecycler.setVisibility(View.GONE);
mEmptyView.setVisibility(View.VISIBLE);
} else {
mMessagesRecycler.setVisibility(View.VISIBLE);
mEmptyView.setVisibility(View.GONE);
}
}
#Override
protected void onError(FirebaseFirestoreException e) {
Snackbar.make(view.findViewById(android.R.id.content),
"Error: check logs for info.", Snackbar.LENGTH_LONG).show();
}
};
mMessagesRecycler.setLayoutManager(new LinearLayoutManager(getActivity()));
mMessagesRecycler.setAdapter(mAdapter);
}
DetailMessageActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_message_detail);
String messageId = getIntent().getExtras().getString(KEY_MESSAGE_ID);
if (messageId == null) {
throw new IllegalArgumentException("Must pass extra " + KEY_MESSAGE_ID);
}
mFirestore = FirebaseFirestore.getInstance();
mMessageRef = mFirestore.collection("messages").document(messageId);
}
#Override
public void onEvent(DocumentSnapshot snapshot, FirebaseFirestoreException e) {
if (e != null) {
Log.w(TAG, "message:onEvent", e);
return;
}
onMessageLoaded(snapshot.toObject(Messages.class));
}
private void onMessageLoaded(Messages message) {
mDetailedHeader.setText(message.getHeader());
mDetailedHeader.setText(message.getSender());
mDetailedMessage.setText(message.getMessage());
mDetailedDate.setText(message.getDate());
}
}
Related
This question already has answers here:
Explanation of ClassCastException in Java
(12 answers)
Closed 1 year ago.
Every time I click on a profile in my application, it causes this crash and error and I wanted to know why and try to find it.
The error:
java.lang.ClassCastException: java.lang.Long cannot be cast to java.util.List
at com.example.soulforge.fragments.Profile.lambda$loadBasicData$4$Profile(Profile.java:274)
at com.example.soulforge.fragments.-$$Lambda$Profile$KwoPqF2dchhRaWfrPFWRwwexTfQ.onEvent(Unknown Source:4)
at com.google.firebase.firestore.DocumentReference.lambda$addSnapshotListenerInternal$2(DocumentReference.java:504)
at com.google.firebase.firestore.DocumentReference$$Lambda$3.onEvent(Unknown Source:6)
at com.google.firebase.firestore.core.AsyncEventListener.lambda$onEvent$0(AsyncEventListener.java:42)
at com.google.firebase.firestore.core.AsyncEventListener$$Lambda$1.run(Unknown Source:6)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
The part of the profile that causes the issue
followersList = (List<Object>) value.get("followers");
followingList = (List<Object>) value.get("following");
and the whole profile.java
public class Profile extends Fragment {
boolean isMyProfile = true;
String uid;
String userUID;
FirestoreRecyclerAdapter<PostImageModel, PostImageHolder> adapter;
private TextView nameTv, toolbarNameTv, statusTv, followingCountTv, followersCountTv, postCountTv;
private CircleImageView profileImage;
private Button followBtn;
private RecyclerView recyclerView;
private LinearLayout countLayout;
private FirebaseUser user;
private ImageButton editProfileBtn;
List<Object> followersList, followingList, followingList_2;
boolean isFollowed;
DocumentReference userRef, myRef;
public Profile() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_profile, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
init(view);
myRef = FirebaseFirestore.getInstance().collection("Users")
.document(user.getUid());
if (IS_SEARCHED_USER) {
isMyProfile = false;
userUID = USER_ID;
loadData();
} else {
isMyProfile = true;
userUID = user.getUid();
}
if (isMyProfile) {
editProfileBtn.setVisibility(View.VISIBLE);
followBtn.setVisibility(View.GONE);
countLayout.setVisibility(View.VISIBLE);
} else {
editProfileBtn.setVisibility(View.GONE);
followBtn.setVisibility(View.VISIBLE);
countLayout.setVisibility(View.GONE);
}
userRef = FirebaseFirestore.getInstance().collection("Users")
.document(userUID);
loadBasicData();
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 3));
loadPostImages();
recyclerView.setAdapter(adapter);
clickListener();
}
private void loadData() {
myRef.addSnapshotListener(new EventListener<DocumentSnapshot>() {
#Override
public void onEvent(#Nullable DocumentSnapshot value, #Nullable FirebaseFirestoreException error) {
if (error != null) {
Log.e("Tag_b", error.getMessage());
return;
}
if (value == null || !value.exists()) {
return;
}
followingList_2 = (List<Object>) value.get("Following");
}
});
}
private void clickListener() {
followBtn.setOnClickListener(v -> {
if (isFollowed) {
followersList.remove(user.getUid());
followingList_2.remove(userUID);
final Map<String, Object> map_2 = new HashMap<>();
map_2.put("following", followingList_2);
Map<String, Object> map = new HashMap<>();
map.put("followers", followersList);
userRef.update(map).addOnCompleteListener(task -> {
if (task.isSuccessful()) {
followBtn.setText("Follow");
myRef.update(map_2).addOnCompleteListener(task1 -> {
if (task1.isSuccessful()) {
Toast.makeText(getContext(), "UnFollowed", Toast.LENGTH_SHORT).show();
} else {
Log.e("Tag_3", task1.getException().getMessage());
}
});
} else {
Log.e("Tag", "" + task.getException().getMessage());
}
});
} else {
followersList.add(user.getUid());
followingList_2.add(userUID);
Map<String, Object> map_2 = new HashMap<>();
map_2.put("following", followingList_2);
Map<String, Object> map = new HashMap<>();
map.put("followers", followersList);
userRef.update(map).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
followBtn.setText("UnFollow");
myRef.update(map_2).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText(getContext(), "Followed", Toast.LENGTH_SHORT).show();
} else {
Log.e("Tag", " " + task.getException().getMessage());
}
}
});
} else {
Log.e("Tag", "" + task.getException().getMessage());
}
}
});
}
});
editProfileBtn.setOnClickListener(v -> {
CropImage.activity()
.setGuidelines(CropImageView.Guidelines.ON)
.setAspectRatio(1, 1)
.start(requireContext(), Profile.this);
});
}
private void init(View view) {
Toolbar toolbar = view.findViewById(R.id.toolbar);
assert getActivity() != null;
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
nameTv = view.findViewById(R.id.nameTv);
toolbarNameTv = view.findViewById(R.id.toolbarNameTV);
statusTv = view.findViewById(R.id.statusTv);
followersCountTv = view.findViewById(R.id.followersCountTv);
followingCountTv = view.findViewById(R.id.followingCountTv);
postCountTv = view.findViewById(R.id.postCountTv);
profileImage = view.findViewById(R.id.profileImage);
followBtn = view.findViewById(R.id.followBtn);
recyclerView = view.findViewById(R.id.recyclerView);
countLayout = view.findViewById(R.id.countLayout);
editProfileBtn = view.findViewById(R.id.edit_profileImage);
FirebaseAuth auth = FirebaseAuth.getInstance();
user = auth.getCurrentUser();
}
private void loadBasicData() {
userRef.addSnapshotListener((value, error) -> {
if (error != null) {
Log.e("Tag_0", error.getMessage());
return;
}
assert value != null;
if (value.exists()) {
String name = value.getString("name");
String status = value.getString("status");
String profileURL = value.getString("profileImage");
nameTv.setText(name);
toolbarNameTv.setText(name);
statusTv.setText(status);
followersList = (List<Object>) value.get("followers");
followingList = (List<Object>) value.get("following");
followersCountTv.setText("" + followersList.size());
followingCountTv.setText("" + followingList.size());
try {
Glide.with(getContext().getApplicationContext())
.load(profileURL)
.placeholder(R.drawable.ic_person)
.timeout(6500)
.into(profileImage);
} catch (Exception e) {
e.printStackTrace();
}
if (followingList.contains(userUID)) {
followBtn.setText("UnFollow");
isFollowed = true;
} else {
isFollowed = false;
followBtn.setText("Follow");
}
}
});
postCountTv.setText("" + LIST_SIZE);
}
private void loadPostImages() {
DocumentReference reference = FirebaseFirestore.getInstance().collection("Users").document(userUID);
Query query = reference.collection("Post Images");
FirestoreRecyclerOptions<PostImageModel> options = new FirestoreRecyclerOptions.Builder<PostImageModel>()
.setQuery(query, PostImageModel.class)
.build();
adapter = new FirestoreRecyclerAdapter<PostImageModel, PostImageHolder>(options) {
#NonNull
#Override
public PostImageHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.profile_image_items, parent, false);
return new PostImageHolder(view);
}
#Override
protected void onBindViewHolder(#NonNull PostImageHolder holder, int position, #NonNull PostImageModel model) {
Glide.with(holder.itemView.getContext().getApplicationContext())
.load(model.getImageUrl())
.timeout(6500)
.into(holder.imageView);
}
};
}
#Override
public void onStart() {
super.onStart();
adapter.startListening();
}
#Override
public void onStop() {
super.onStop();
adapter.stopListening();
}
#Override
public void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE && resultCode == RESULT_OK) {
CropImage.ActivityResult result = CropImage.getActivityResult(data);
Uri uri = result.getUri();
uploadImage(uri);
}
}
private void uploadImage(Uri uri) {
StorageReference reference = FirebaseStorage.getInstance().getReference().child("Profile Images");
reference.putFile(uri)
.addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
#Override
public void onComplete(#NonNull Task<UploadTask.TaskSnapshot> task) {
if (task.isSuccessful()) {
reference.getDownloadUrl()
.addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
String imageURL = uri.toString();
UserProfileChangeRequest.Builder request = new UserProfileChangeRequest.Builder();
request.setPhotoUri(uri);
user.updateProfile(request.build());
Map<String, Object> map = new HashMap<>();
map.put("profileImage", imageURL);
map.put("date", FieldValue.serverTimestamp());
FirebaseFirestore.getInstance().collection("Users")
.document(user.getUid())
.update(map).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful())
Toast.makeText(getContext(), "Updated Successfully", Toast.LENGTH_SHORT).show();
else
Toast.makeText(getContext(), "Error: " + task.getException().getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
});
} else {
Toast.makeText(getContext(), "Error: " + task.getException().getMessage(), Toast.LENGTH_SHORT).show();
}
}
});
}
private static class PostImageHolder extends RecyclerView.ViewHolder {
private ImageView imageView;
public PostImageHolder(#NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.imageView);
}
}
}
Why is this happening ,and why is it a Long instead of being a list and causing all this issues?
The problem is that the data is of Long class and you are trying to cast it to List
What you should try is
Map<String, Object> followerMap= new HashMap<>();
followerMap= value.getData();
assert followerMap!= null;
for (Map.Entry<String, Object> e : followerMap.entrySet()) {
long following= e.getValue();
followingList_2 .add(following);
}
I have a RecyclerView.Adapter in my code which is used to set elements in my layout file, but due to an UNKNOWN error, I am not able to display those elements. I am able to retrieve the data from Firebase, able to reach the onBindViewHolder but, there are no end results.
Logcat
D/HomeViewModel: Data was added to the LiveData List.[secondQuestion, question]
D/HomeAdapter: onCreateViewHolder
onBindViewHolder
HomeAdapter.java
#Override
public void onBindViewHolder(#NonNull HomeAdapter.ViewHolder holder, final int position) {
if (mQuestions.isEmpty()) {
String question = mQuestions.get(position);
holder.question.setText(question);
}
}
HomeFragment.java
homeViewModel.getmQuestionsData().observe(getViewLifecycleOwner(), new Observer<List<String>>() {
#Override
public void onChanged(List<String> mQuestionList) {
mQuestion.addAll(mQuestionList);
// TODO: The FUCKING Bug is around here
adapter.notifyDataSetChanged();
}
});
HomeViewModel.java
MutableLiveData<List<String>> getmQuestionsData() {
repository.getPredictiousCol()
//.whereEqualTo("exists","true")
//
.addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot queryDocumentSnapshots, #Nullable FirebaseFirestoreException e) {
if (e != null) {
Log.d(TAG, "Question could not be retrieved " + e);
mQuestionsData = null;
return;
}
List<String> questionList = new ArrayList<>();
assert queryDocumentSnapshots != null;
for (QueryDocumentSnapshot doc : queryDocumentSnapshots) {
if (doc.get("question") != null) {
questionList.add((String) doc.get("question"));
}
}
mQuestionsData.postValue(questionList);
Log.d(TAG, "Data was added to the LiveData List." + questionList);
}
});
return mQuestionsData;
}
Comment down below if you want more of my code or any other related queries.
THANK YOU!
I think your error is here:
#Override
public void onBindViewHolder(#NonNull HomeAdapter.ViewHolder holder, final int position) {
if (mQuestions.isEmpty()) {
String question = mQuestions.get(position);
holder.question.setText(question);
}
}
You're in essence saying if you have nothing in your list then set the questions to your list.... It should say:
#Override
public void onBindViewHolder(#NonNull HomeAdapter.ViewHolder holder, final int position) {
if (!mQuestions.isEmpty()) {
String question = mQuestions.get(position);
holder.question.setText(question);
}
}
note the ! before mQuestions.isEmpty() meaning if the mQuestion is not empty...
I've been stuck in a situation and i need some help over here. There are many articles on this topic here but none of them answered my question. I want to implement onBackPressed() in fragments and show dialog box which shows to exit the application or not. Any help would be appreciated.
LoginFragment.java
public class LoginFragment extends Fragment {
public static final String TAG = LoginFragment.class.getSimpleName();
private EditText mEtEmail;
private EditText mEtPassword;
private Button mBtLogin;
private TextView mTvRegister;
private TextView mTvForgotPassword;
private TextInputLayout mTiEmail;
private TextInputLayout mTiPassword;
private ProgressBar mProgressBar;
private CompositeSubscription mSubscriptions;
private SharedPreferences mSharedPreferences;
#NonNull
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_login,container,false);
mSubscriptions = new CompositeSubscription();
initViews(view);
initSharedPreferences();
return view;
}
private void initViews(View v) {
mEtEmail = v.findViewById(R.id.et_email);
mEtPassword = v.findViewById(R.id.et_password);
mBtLogin = v.findViewById(R.id.btn_login);
mTiEmail = v.findViewById(R.id.ti_email);
mTiPassword = v.findViewById(R.id.ti_password);
mProgressBar = v.findViewById(R.id.progress);
mTvRegister = v.findViewById(R.id.tv_register);
mTvForgotPassword = v.findViewById(R.id.tv_forgot_password);
mBtLogin.setOnClickListener(view -> login());
mTvRegister.setOnClickListener(view -> goToRegister());
mTvForgotPassword.setOnClickListener(view -> showDialog());
}
private void initSharedPreferences() {
mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
}
private void login() {
setError();
String email = mEtEmail.getText().toString();
String password = mEtPassword.getText().toString();
int err = 0;
if (!validateEmail(email)) {
err++;
mTiEmail.setError("Email should be valid !");
}
if (!validateFields(password)) {
err++;
mTiPassword.setError("Password should not be empty !");
}
if (err == 0) {
loginProcess(email,password);
mProgressBar.setVisibility(View.VISIBLE);
} else {
showSnackBarMessage("Enter Valid Details !");
}
}
private void setError() {
mTiEmail.setError(null);
mTiPassword.setError(null);
}
private void loginProcess(String email, String password) {
mSubscriptions.add(NetworkUtil.getRetrofit(email, password).login()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(this::handleResponse,this::handleError));
}
private void handleResponse(Response response) {
mProgressBar.setVisibility(View.GONE);
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putString(Constants.TOKEN,response.getToken());
editor.putString(Constants.EMAIL,response.getMessage());
editor.apply();
mEtEmail.setText(null);
mEtPassword.setText(null);
Intent intent = new Intent(getActivity(), HomeActivity.class);
startActivity(intent);
}
private void handleError(Throwable error) {
mProgressBar.setVisibility(View.GONE);
if (error instanceof HttpException) {
Gson gson = new GsonBuilder().create();
try {
String errorBody = ((HttpException) error).response().errorBody().string();
Response response = gson.fromJson(errorBody,Response.class);
showSnackBarMessage(response.getMessage());
} catch (IOException e) {
e.printStackTrace();
}
} else {
showSnackBarMessage("No Internet Connection!");
}
}
private void showSnackBarMessage(String message) {
if (getView() != null) {
Snackbar.make(getView(),message,Snackbar.LENGTH_SHORT).show();
}
}
private void goToRegister(){
FragmentTransaction ft = getFragmentManager().beginTransaction();
RegisterFragment fragment = new RegisterFragment();
ft.replace(R.id.fragmentFrame,fragment,RegisterFragment.TAG);
ft.addToBackStack(null).commit();
}
private void showDialog(){
ResetPasswordDialog fragment = new ResetPasswordDialog();
fragment.show(getFragmentManager(), ResetPasswordDialog.TAG);
}
#Override
public void onDestroy() {
super.onDestroy();
mSubscriptions.unsubscribe();
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity implements ResetPasswordDialog.Listener {
public static final String TAG = MainActivity.class.getSimpleName();
private LoginFragment mLoginFragment;
private ResetPasswordDialog mResetPasswordDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
loadFragment();
}
}
private void loadFragment() {
if (mLoginFragment == null) {
mLoginFragment = new LoginFragment();
}
getFragmentManager().beginTransaction().replace(R.id.fragmentFrame, mLoginFragment, LoginFragment.TAG).commit();
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
String data = intent.getData().getLastPathSegment();
Log.d(TAG, "onNewIntent: " + data);
mResetPasswordDialog = (ResetPasswordDialog) getFragmentManager().findFragmentByTag(ResetPasswordDialog.TAG);
if (mResetPasswordDialog != null)
mResetPasswordDialog.setToken(data);
}
#Override
public void onPasswordReset(String message) {
showSnackBarMessage(message);
}
private void showSnackBarMessage(String message) {
Snackbar.make(findViewById(R.id.activity_main), message, Snackbar.LENGTH_SHORT).show();
}
}
In My Login Fragment, I want to show a dialog box "Do you want to exit the application or not". On Yes it dismiss the current fragment and end the activity otherwise it'll remain active. Help please!
You can even try this way
MainActivity.java
#Override
public void onBackPressed() {
if (getFragmentManager() != null && getFragmentManager().getBackStackEntryCount() >= 1) {
String fragmentTag = getFragmentManager().findFragmentById(R.id.frame_container).getTag();
if(fragmentTag.equals(LoginFragment.getTag())){
// show Dialog code
}else{
super.onBackPressed();
}
} else {
super.onBackPressed();
}
}
Add this code in your main activity so that when login fragment is added and you click backpress, then on first if the fragment is added to fragment transaction, then first it finds the fragment and check if its tag is equals to the login fragment tag. Then if both tag matches, then you can show your exit alert dialog.
Android team has prepared a new way of handling the back button pressed on Fragments for us, so you should check this out. It's called OnBackPressedDispatcher.
You need to register OnBackPressedCallback to the fragment where do you want to intercept back button pressed. You can do it like this inside of the Fragment:
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
OnBackPressedCallback callback = new OnBackPressedCallback(true) {
#Override
public void handleOnBackPressed() {
//show exit dialog
}
};
requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);
}
So basically I'm collecting data from a json url in my listview. It's a chatroom type of app and in the lists I want to sync the chatroom contact lists with latest message and timestamps.
When the json gets updated I'm calling the fuction.
public void addGroupAdapter() {
Firebase jsonurl = new Firebase("firebase url");
jsonurl.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
ContactListAdapter adapter = new ContactListAdapter(getContext(),dataSnapshot);
try {
Log.i("Response Array fire",new JSONArray(dataSnapshot.getValue(String.class)).toString());
if (!adapted){
chatLists.setAdapter(adapter);
adapted = true;
}else {
Log.i("update",dataSnapshot.getValue(String.class));
adapter.setContactList(dataSnapshot);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
That Json data is stored in the firebase database .
chatLists.setAdapter(adapter) works well.
But when I try to update. notifyDataSetChanged(); doesn't work.
new ContactListAdapter(getContext(),dataSnapshot).notifyDataSetChanged();
I also tried invalidateviews method and same result. So where am I doing wrong?
After reading answers I tried this. SO now this my adapter class,
class ContactListAdapter extends BaseAdapter {
Context c;
List lists;
Type type = new TypeToken<List<ChatroomLists>>(){}.getType();
JsonParser parser = new JsonParser();
ArrayList<ChatroomLists> ob1 = new ArrayList<ChatroomLists>();
public void setContactList(DataSnapshot dataSnapshot) {
Type listType = new TypeToken<ArrayList<ChatroomLists>>() {
}.getType();
ob1 = new Gson().fromJson((JsonArray)parser.parse(dataSnapshot.getValue(String.class)),listType);
Log.i("setContactList",dataSnapshot.getValue(String.class));
notifyDataSetChanged();
}
ContactListAdapter(Context c, DataSnapshot group_name) {
this.c = c;
this.groupids = group_name;
Type listType = new TypeToken<ArrayList<ChatroomLists>>() {
}.getType();
ob1 = new Gson().fromJson((JsonArray)parser.parse(group_name.getValue(String.class)),listType);
}
#Override
public int getCount() {
return ob1.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View row = convertView;
GroupChat.viewHolder holder = null;
if (row == null) {
LayoutInflater inflater = (LayoutInflater) c.getSystemService (Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate (R.layout.chat_list_style, parent, false);
holder = new GroupChat.viewHolder(row);
row.setTag (holder);
} else {
holder = (GroupChat.viewHolder) row.getTag ();
}
ChatroomLists chatroomLists = ob1.get(position);
Iterator<ChatroomLists> iter = ob1.iterator();
String id = chatroomLists.getId();
String time = chatroomLists.getTimestamp();
Log.i("updated data",id + time);
viewHolder finalHolder = holder;
Firebase chatlink = new Firebase ("firebase link");
chatlink.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot d: dataSnapshot.getChildren()){
finalHolder.user_message.setText (dataSnapshot.child(d.getKey()).child("message").getValue(String.class));
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
Firebase imageurl = new Firebase("firebase link");
imageurl.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Glide.with (getActivity ())
.load (dataSnapshot.getValue(String.class))
.error (R.drawable.man)
.into (finalHolder.user_img);
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
holder.user_name.setText (id);
row.setOnClickListener (new View.OnClickListener () {
#Override
public void onClick(View v) {
Intent intent = new Intent (getActivity (), ChatRoom.class);
intent.putExtra ("group_name", id);
startActivity (intent);
}
});
registerForContextMenu (row);
return row;
}
}
But it's still not updating.. :(
UPDATE: Listview was so buggy in this case. And I changed to Recyclerview. Now everything is working smoothly.
This is because you are creating new adapter instance instead of updating data on existing adapter which is set on list/recyclerview.
private ContactListAdapter mAdatper;
public void addGroupAdapter() {
Firebase jsonurl = new Firebase("firebase url");
jsonurl.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
try {
Log.i("Response Array fire",new JSONArray(dataSnapshot.getValue(String.class)).toString());
if (!adapted){
mAdatper = new ContactListAdapter(getContext(),dataSnapshot);
chatLists.setAdapter(mAdapter);
adapted = true;
}else {
Log.i("update",dataSnapshot.getValue(String.class));
mAdatper.setContactList(dataSnapshot);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
}
In your adapter, add setter method.
public void setContactList(DataSnapshot dataSnapshot) {
// set contactList here
notifyDataSetChanged();
}
Hope it might be helpful for you.
You are calling notifyDataSetChanged() on a new instance of the adapter everytime. You should call it on the same adapter that you set on the list. And you should update the data in that particular instance of the adapter
In your else case you are creating a new ContactListAdapter but you are not attaching that adapter to your chatLists. Anyway, you do not need to create a new CustomAdapter instance, just create a update method within your CustomAdapter and call it passing new dataSnapshot data.
You can Try something as the following inside your CustomAdapter.java:
public void updateData(Data data) {
this.dataList = data;
notifyDataSetChanged();
}
Then back into your addGroupAdapter method just call that method
I'm currently getting a ClassCastException in my android app caused by "activity cannot be cast to interface".
Here is my code:
Logcat says the Exception is thrown in the onAttach part in MovieGridFragment on the line "this.clickListener = (clickInterfaceHelper) context;".
My Interface:
public interface clickInterfaceHelper {
void clickOnItem(int id);
void favoriteMovieItem(int movieId); }
The Fragment Class:
public class MovieGridFragment extends Fragment {
public clickInterfaceHelper clickListener;
private int index;
private GridView movieGridView;
public List<movieData> movieDataList = new ArrayList<>();
public MovieGridFragment() {} //empty constructor
#Override
public void onAttach(Context context) {
this.clickListener = (clickInterfaceHelper) context;
super.onAttach(context);
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
if(savedInstanceState != null) {
if (!movieDataList.isEmpty()) {
movieDataList = Arrays.asList((movieData[]) savedInstanceState.getSerializable("OLDMOVIEDATA"));
}
}
super.onCreate(savedInstanceState);
}
The MainActivity:
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setHasOptionsMenu(true);
View rootView = inflater.inflate(R.layout.movie_display_fragment, container, false);
movieGridView = (GridView) rootView.findViewById(R.id.gv_movie_display);
movieAdapter adapter = new movieAdapter(getActivity(),movieDataList);
adapter.notifyDataSetChanged();
movieGridView.setAdapter(adapter);
movieGridView.setSelection(index);
movieGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(clickListener != null)
clickListener.clickOnItem(position);
}
});
return rootView;
}
#Override
public void onSaveInstanceState(Bundle outState) {
index = movieGridView.getFirstVisiblePosition();
outState.putSerializable("OLDMOVIEDATA",movieData.movieDataArray);
super.onSaveInstanceState(outState);
}}
and mainactivity:
public class MainActivity extends AppCompatActivity implements clickInterfaceHelper {
public static String sorterString = null;
public static String urlBase = "https://api.themoviedb.org/3/movie/";
public static String urlFinal = null;
RequestQueue requestQueue;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.activity_container, new MovieGridFragment())
.commit();
movieData.movieDataPosition = 0;
}
if(savedInstanceState != null) {
sorterString = savedInstanceState.getString("SORTER");
}
if(savedInstanceState == null)
movieData.movieDataPosition = 0;
if(sorterString==null)
sorterString="popular?";
if(sorterString!="favorite" && sorterString!=null) {
if(networkChecker.isNetworkAvailableChecker(this)) {
movieRequest();
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu_act, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id == R.id.m_popularity_action) {
if(sorterString != "popular?") {
sorterString = "popular?";
if(networkChecker.isNetworkAvailableChecker(this))
movieRequest();
}
return true;
}
if(id == R.id.m_action_voter) {
if(sorterString != "top_rated?") {
sorterString = "top_rated?";
if(networkChecker.isNetworkAvailableChecker(this))
movieRequest();
}
return true;
}
if(id == R.id.m_favorite_btn) {
if(sorterString != "favorite") {
SQLiteOpenHelper helper = new movieDataDbHelper(this);
SQLiteDatabase database = helper.getReadableDatabase();
Cursor cursor= database.query(movieDataContract.contractEntry.TABLE_NAME,
new String[] {
movieDataContract.contractEntry.ID,
movieDataContract.contractEntry.IMG_PATH},null,null,null,null,null);
if(cursor.getCount() == 0) {
Toast.makeText(this, "there are no favorite movies yet!",Toast.LENGTH_SHORT).show();
} else {
sorterString = "favorite";
showFavoriteFragment();
}
database.close();
helper.close();
cursor.close();
}
return true;
}
return super.onOptionsItemSelected(item);
}
public void showFavoriteFragment() {
favoriteMoviesDetailsFragment fragment = new favoriteMoviesDetailsFragment();
try {
getFragmentManager().beginTransaction().replace(R.id.activity_container,fragment).commit();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
outState.putString("SORTER", sorterString);
outState.putInt("POSITION",movieData.movieDataPosition);
super.onSaveInstanceState(outState, outPersistentState);
}
public void movieRequest() {
urlFinal = urlBase + sorterString + movieData.apiKey;
urlFinal.trim();
requestQueue = Volley.newRequestQueue(this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, urlFinal, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray array = response.getJSONArray("results");
movieData.movieDataArray = new movieData[array.length()];
for (int i = 0; i < array.length(); i++) {
movieData movie = new movieData();
JSONObject jsonObject = array.getJSONObject(i);
//movie.setPosition(i);
movie.setMovieId(jsonObject.getString("id"));
movie.setMovieImagePath(jsonObject.getString("poster_path"));
movie.setMovieTitle(jsonObject.getString("original_title"));
movie.setMoviePlot(jsonObject.getString("overview"));
movie.setMovieVoting(jsonObject.getString("vote_average"));
movie.setMovieReleaseDate(jsonObject.getString("release_date"));
movieData.movieDataArray[i] = movie;
}
MovieGridFragment gridFragment = new MovieGridFragment();
gridFragment.movieDataList = Arrays.asList(movieData.movieDataArray); //hier wird datalist eigentlich zugewiesen
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.activity_container, gridFragment);
try {
transaction.commitAllowingStateLoss();
} catch (Exception e) {
e.printStackTrace();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("volley", String.valueOf(error));
}
}
);
requestQueue.add(jsonObjectRequest);
}
#Override
public void clickOnItem(int id) {
movieData.movieDataPosition = id;
if(movieData.movieDataArray == null) {
movieRequest();
} else {
Intent intent = new Intent(this, detailsActivity.class);
intent.putExtra("FRAGMENT","MOVIE");
startActivity(intent);
}
}
#Override
public void favoriteMovieItem(int movieId) {
movieData.dbPosition = movieId;
Intent intent = new Intent(this,detailsActivity.class);
intent.putExtra("FRAGMENT","favorite");
startActivity(intent);
} }
You can try this
this.clickListener = (MainActivity) getActivity();
You get the FragmentActivity and cast it into your MainActivity
EDIT:
I suggest you to add a function in your fragment like :
public void setListener(clickInterfaceHelper listener) {
this.clickListener = listener;
}
And in your activity :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedInstanceState == null) {
MovieGridFragment fragment = new MovieGridFragment();
fragment.setListener(this); // some change here
getSupportFragmentManager().beginTransaction()
.add(R.id.activity_container, fragment)
.commit();
movieData.movieDataPosition = 0;
}
if(savedInstanceState != null) {
sorterString = savedInstanceState.getString("SORTER");
}
if(savedInstanceState == null)
movieData.movieDataPosition = 0;
if(sorterString==null)
sorterString="popular?";
if(sorterString!="favorite" && sorterString!=null) {
if(networkChecker.isNetworkAvailableChecker(this)) {
movieRequest();
}
}
}
.... no relevant functions
public void movieRequest() {
urlFinal = urlBase + sorterString + movieData.apiKey;
urlFinal.trim();
requestQueue = Volley.newRequestQueue(this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, urlFinal, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray array = response.getJSONArray("results");
movieData.movieDataArray = new movieData[array.length()];
for (int i = 0; i < array.length(); i++) {
movieData movie = new movieData();
JSONObject jsonObject = array.getJSONObject(i);
//movie.setPosition(i);
movie.setMovieId(jsonObject.getString("id"));
movie.setMovieImagePath(jsonObject.getString("poster_path"));
movie.setMovieTitle(jsonObject.getString("original_title"));
movie.setMoviePlot(jsonObject.getString("overview"));
movie.setMovieVoting(jsonObject.getString("vote_average"));
movie.setMovieReleaseDate(jsonObject.getString("release_date"));
movieData.movieDataArray[i] = movie;
}
MovieGridFragment gridFragment = new MovieGridFragment();
gridfragment.setListener(this); // some change here
gridFragment.movieDataList = Arrays.asList(movieData.movieDataArray); //hier wird datalist eigentlich zugewiesen
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.activity_container, gridFragment);
try {
transaction.commitAllowingStateLoss();
} catch (Exception e) {
e.printStackTrace();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("volley", String.valueOf(error));
}
}
);
requestQueue.add(jsonObjectRequest);
}
Hope this helps.
The context passed in is not necessarily your activity. It could be a wrapper around it with various theming and other overrides. You can never assume that when passed a Context, you're passed an Activity. If you need a reference to a click handler, write a setClickHandler function and call it explicitly.
Even if it is the Activity, the app doesn't know that- at that point its a Context. You'd need to explicitly cast it, which may not work (and may work on some versions of the OS and not others) due to paragraph 1.
Try to put your interface inside fragment class.
public class MovieGridFragment extends Fragment {
public clickInterfaceHelper clickListener;
private int index;
private GridView movieGridView;
public List<movieData> movieDataList = new ArrayList<>();
public MovieGridFragment() {} //empty constructor
#Override
public void onAttach(Context context) {
this.clickListener = (clickInterfaceHelper) context;
super.onAttach(context);
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
if(savedInstanceState != null) {
if (!movieDataList.isEmpty()) {
movieDataList = Arrays.asList((movieData[]) savedInstanceState.getSerializable("OLDMOVIEDATA"));
}
}
super.onCreate(savedInstanceState);
}
public interface clickInterfaceHelper {
void clickOnItem(int id);
void favoriteMovieItem(int movieId);
}
}
To all android beginners, you can use the interface like below-mentioned way.
Define an Interface,
public interface CallBack {
String stringValue(String s);
}
In Fragment,
Callback mCallback;
In onAttach(Context context) method of your fragment,
mCallback = (Callback) context; // Casting to the activity
mcallback.stringValue("Your message");
Then in your Activity, you must implement the interface else you will get
classcastException
public class MainActivity implements CallBack{
#Override
public String stringValue(String s) {
// Here you will get the value from the fragment
return s;
}
}
It's not advisable to pass values between two fragments directly using interfaces. You should use the activity as a mediator while passing values.