I am trying to get list of posts in categories with deep linking but it returns Unresolved reference
Screenshots
Documents
my code
Errors
Code
class CategoryLinkDetails : Fragment() {
private lateinit var mInterstitialAd: InterstitialAd
private lateinit var homeViewModel: HomeViewModel
private var recyclerView: RecyclerView? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
super.onCreate(savedInstanceState)
homeViewModel = ViewModelProviders.of(this).get(HomeViewModel::class.java)
val root = inflater.inflate(R.layout.categorylink_details, container, false)
recyclerView = root.findViewById(R.id.categorylinkRecycle)
handleIntent(intent)
return root
}
// api code
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
handleIntent(intent)
}
private fun handleIntent(intent: Intent) {
val appLinkAction = intent.action
val appLinkData: Uri? = intent.data
if (Intent.ACTION_VIEW == appLinkAction) {
appLinkData?.lastPathSegment?.also { recipeId ->
Uri.parse("content://com.my.app/categories/")
.buildUpon()
.appendPath(recipeId)
.build().also { appData ->
// Instantiate the RequestQueue.
val queue = Volley.newRequestQueue(activity)
val url = "https://example.com/v1/categories/$recipeId"
// Request a string response from the provided URL.
val stringRequest = StringRequest(
Request.Method.GET, url,
Response.Listener<String> { response ->
val jsonArray = JSONArray(response)
val list: ArrayList<MyCategoryLink> = ArrayList()
for (i in 0 until jsonArray.length()) {
val jsonObject = jsonArray.getJSONObject(i)
list.add(parseData(jsonObject))
}
// here you will have the complete list of data in your "list" variable
categoriesRecycle.layoutManager = LinearLayoutManager(activity)
Log.d("my list", list.toString())
categoriesRecycle.adapter = MyCategoryListAdapter(list)
},
Response.ErrorListener { error ->
//displaying the error in toast if occurrs
Toast.makeText(activity, error.message, Toast.LENGTH_SHORT)
.show()
})
// Add the request to the RequestQueue.
queue.add(stringRequest)
}
}
}
}
private fun parseData(jsonObject: JSONObject): MyCategoryLink {
var listingObject = MyCategoryLink(
jsonObject.getString("name"),
jsonObject.getString("slug"),
HtmlCompat.fromHtml(jsonObject.getString("body"), HtmlCompat.FROM_HTML_MODE_COMPACT),
jsonObject.getString("image")
)
return listingObject
}
}
NOTE:
The only difference between my code and documentation is that I use Fragment because I need to show a list of posts but in docs they used Activity
Any idea?
You need to handle intent data in activity class then you need to pass intent to fragment constructor
refer below code.
class TestActivity :AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
handleIntent(intent)
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
handleIntent(intent)
}
private fun handleIntent(intent: Intent?) {
// now from here you can add your fragment here
var categoryDetails = CategoryDetailsFragment(intent)
var ft = supportFragmentManager.beginTransaction()
ft.add(R.id.container,categoryDetails)
}}
I hope this will help.
Related
class ProfileFragment : Fragment() {
private lateinit var firestore: FirebaseFirestore
private lateinit var auth: FirebaseAuth
private lateinit var storage: FirebaseStorage
private lateinit var activityResultLauncher : ActivityResultLauncher<Intent>
private lateinit var permissionLauncher : ActivityResultLauncher<String>
var selectedPicture : Uri? = null
private var _binding: FragmentProfileBinding? = null
private val binding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
auth = Firebase.auth
firestore = Firebase.firestore
storage = Firebase.storage
registerLauncher()
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentProfileBinding.inflate(inflater, container, false)
val view = binding.root
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val navController = Navigation.findNavController(requireActivity(), R.id.fragment)
binding.bottomNavigationView.setupWithNavController(navController)
imageUpload.setOnClickListener {
if (ContextCompat.checkSelfPermission(requireContext(),android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
if (ActivityCompat.shouldShowRequestPermissionRationale(requireActivity(),android.Manifest.permission.READ_EXTERNAL_STORAGE)){
Snackbar.make(view,"Galeriye erişmek için izin vermeniz gerekmektedir.",Snackbar.LENGTH_INDEFINITE).setAction("İzin Ver"){
permissionLauncher.launch(android.Manifest.permission.READ_EXTERNAL_STORAGE)
}.show()
}else{
permissionLauncher.launch(android.Manifest.permission.READ_EXTERNAL_STORAGE)
}
}else{
val intentToGallery = Intent(Intent.ACTION_PICK,MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
activityResultLauncher.launch(intentToGallery)
}
val uuid = UUID.randomUUID()
val imageName = "$uuid.jpg"
val reference = storage.reference
val imageReference = reference.child("images").child(imageName)
if (selectedPicture!=null){
imageReference.putFile(selectedPicture!!).addOnSuccessListener {
val uploadPictureReference = storage.reference.child("images").child(imageName)
uploadPictureReference.downloadUrl.addOnSuccessListener {
val downloadUrl = it.toString()
val profileMap = hashMapOf<String, Any>()
profileMap.put("downloadUrl",downloadUrl)
firestore.collection("Profile").add(profileMap).addOnSuccessListener {
}.addOnFailureListener {
Toast.makeText(requireContext(),it.localizedMessage,Toast.LENGTH_SHORT).show()
}
}
}.addOnFailureListener {
Toast.makeText(requireContext(),it.localizedMessage,Toast.LENGTH_SHORT).show()
}
}
}
}
private fun registerLauncher(){
activityResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){result ->
if (result.resultCode == RESULT_OK){
val intentFromResult = result.data
if (intentFromResult !=null){
selectedPicture = intentFromResult.data
selectedPicture?.let {
binding.selectImage.setImageURI(it)
}
}
}
}
permissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()){result->
if (result){
val intentToGallery = Intent(Intent.ACTION_PICK,MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
activityResultLauncher.launch(intentToGallery)
}else{
Toast.makeText(requireContext(),"Galeriye Erişim İçin İzin Gereklidir.", Toast.LENGTH_SHORT).show()
}
}
}
The codes written here belong to the fragment I created the profile page for.
I am trying to upload an image to Firebase Storage by clicking the button with imageUpload id. However, it is not saved to the Storage and the photo I uploaded disappears when I click on a different page.
Do I need to add the codes somewhere other than OnViewCreated?
Also, when I assign an onClick method to a button, image or something else, I cannot call it with the fun method. For example, let uploadImage be the onClick function, not the button's id. I can't define it as 'fun uploadImage' anywhere in the fragment, why?
I have placed buttons on these 6 items now all I need is when a user clicks on a button it has to connect to a api fetch and display content ,similarly clicking on all other buttons should connect to respective api s.Now creating a new activity and new adapter for each is causing redundant code how to implement this properly please help me
home fragment
class Homefragment : Fragment() {
lateinit var buttondept:Button
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val view= inflater.inflate(R.layout.fragment_homefragment, container, false)
buttondept=view.findViewById(R.id.btnDept)
buttondept.setOnClickListener {
val intent=Intent(context,descactivity::class.java)
intent.putExtra("option","department")
startActivity(intent)
}
return view
}
}
desc activity
class descactivity : AppCompatActivity() {
lateinit var recyclerDashBoard: RecyclerView
lateinit var layoutmanager: RecyclerView.LayoutManager
lateinit var recyclerAdapter:Horizontal_RecyclerView
lateinit var progressLayout: RelativeLayout
lateinit var progressBar: ProgressBar
lateinit var button: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_descactivity)
val bookInfoList = arrayListOf<Book>()
recyclerDashBoard = findViewById(R.id.recyclerDashboard)
progressBar = findViewById(R.id.progressbar)
progressLayout = findViewById(R.id.progresslayout)
progressLayout.visibility = View.VISIBLE
val intent=getIntent()
val selectionOption= intent.getStringExtra("option")
val queue = Volley.newRequestQueue(this as Context)
val url = "http://13.235.250.119/v1/book/fetch_books/"
if (ConnectionManager().checkConnectivity(this as Context)) {
val jsonObjectRequest =
object : JsonObjectRequest(Method.GET, url, null, Response.Listener {
try {
progressLayout.visibility = View.GONE
val success = it.getBoolean("success")
if (success) {
val data = it.getJSONArray("data")
for (i in 0 until data.length()) {
val bookJSONObject = data.getJSONObject(i)
val bookobject = Book(
bookJSONObject.getString("book_id"),
bookJSONObject.getString("name"),
bookJSONObject.getString("author"),
bookJSONObject.getString("rating"),
bookJSONObject.getString("price"),
bookJSONObject.getString("image")
)
bookInfoList.add(bookobject)
layoutmanager = LinearLayoutManager(this)
recyclerAdapter =
Horizontal_RecyclerView(this as Context, bookInfoList)
recyclerDashBoard.adapter = recyclerAdapter
recyclerDashBoard.layoutManager = layoutmanager
}
} else {
Toast.makeText(
this as Context,
"some error occurred!!",
Toast.LENGTH_SHORT
).show()
}
} catch (e: JSONException) {
Toast.makeText(
this as Context,
"some unknown error occured!!",
Toast.LENGTH_SHORT
).show()
}
}, Response.ErrorListener {
Toast.makeText(
this as Context,
"volley error occured!!",
Toast.LENGTH_SHORT
).show()
}) {
override fun getHeaders(): MutableMap<String, String> {
val headers = HashMap<String, String>()
headers["content-type"] = "application/json"
headers["token"] = "a07daa7f3efb3b"
return headers
}
}
queue.add(jsonObjectRequest)
}
}
}
I have an application using databinding, livedata, room, kotlin koroutines, viewmodel, retrofit and koin. I have one activity, and two fragments.
UserListFragment: Show in a recyclerview a list of user items.
UserFullProfileFragment: Show the user item detail.
When the application is running, an external API is called to retrieve a list of users and display it in a recyclerview. Then, if I click on one item, an external API is called to get the detail of the current user whith its ID.
The problem is when I click on one item at the first, everything is going well but for following items, this is the detail of previous item which is displayed and so on and so forth.
Any ideas ?
UserRepository:
class UserRepositoryImpl (private val userApi: UserApi, private val userDao: UserDao, private val networkStateManager: NetworkStateManager) : UserRepository {
override suspend fun getUserList(): Result<List<UserListItem>> {
if (networkStateManager.hasNetWorkConnection()) {
return try {
// get user list from user API
val response = userApi.getUserList()
if (response.isSuccessful) {
Log.d("REPO", "get users from api")
response.body()?.let { userResponse ->
Log.d("REPO", "response:$response")
val userList = userResponse.data
// convert user API object to user entity
val entities = userList.map { it.toUserEntity() }
// save user list in database
withContext(Dispatchers.IO) { userDao.addUsers(entities) }
// convert user entity to user model
val userItemList = entities.map { it.toUserListItem() }
return Result.Success(userItemList)
} ?: handleFailure(response)
} else {
handleFailure(response)
}
} catch (e: Exception) {
return Result.Failure(e, e.localizedMessage)
}
} else {
// get user list from database if no network
val data = withContext(Dispatchers.IO) { userDao.findAllUsers() }
return if (data.isNotEmpty()) {
Log.d("REPO", "get users from db")
val userItemList = data.map { it.toUserListItem() }
Result.Success(userItemList)
} else {
Result.Failure(Exception("error"), "no network connection")
}
}
}
override suspend fun getUserFullProfile(userId: String): Result<UserFullProfile> {
if (networkStateManager.hasNetWorkConnection()) {
return try {
// get user from user API
val response = userApi.getUserFullProfile(userId)
if (response.isSuccessful) {
Log.d("REPO", "get users from api")
response.body()?.let { userResponse ->
Log.d("REPO", "response:$userResponse")
// convert user API object to user entity
val userEntity = userResponse.toUserEntity()
// save user data in database
withContext(Dispatchers.IO) { userDao.addUserFullProfile(userEntity) }
// convert user entity to user model
val user = userEntity.toUserFullProfile()
return Result.Success(user)
} ?: handleFailure(response)
} else {
handleFailure(response)
}
} catch (e: Exception) {
return Result.Failure(e, e.localizedMessage)
}
} else {
// get user from database if no network
val data = withContext(Dispatchers.IO) { userDao.getUserById(userId) }
return if (data != null) {
Log.d("REPO", "get users from db")
val user = data.toUserFullProfile()
Result.Success(user)
} else {
Result.Failure(Exception("error"), "no network connection")
}
}
}
UserViewModel:
getUserList and getUserFullProfile are use cases which call the repository
class UserViewModel (private val getUserList: GetUserList, private val getUserFullProfile: GetUserFullProfile) : ViewModel() {
val userList = MutableLiveData<List<UserListItem>>()
val userFullProfile = MutableLiveData<UserFullProfile>()
fun getUserList() {
viewModelScope.launch {
when (val result = getUserList.getUserList()) {
is Result.Success -> userList.value = result.successData
is Result.Failure -> result.exception.localizedMessage
}
}
}
fun getUserFullProfile(userId: String) {
viewModelScope.launch {
when (val result = getUserFullProfile.getUserFullProfile(userId)) {
is Result.Success -> userFullProfile.value = result.successData
is Result.Failure -> result.exception.localizedMessage
}
}
}
UserRecyclerAdaper:
class UserRecyclerAdapter(private val context: Context?, val clickListener: UserClickListener) : RecyclerView.Adapter<UserRecyclerAdapter.UserViewHolder>() {
var userList : List<UserListItem> = ArrayList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
val inflatedView: UserItemBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.context), R.layout.user_item, parent, false)
return UserViewHolder(inflatedView)
}
override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
holder.bindUser(position)
}
override fun getItemCount() = userList.size
fun setUsers(users: List<UserListItem>) {
this.userList = users
notifyDataSetChanged()
}
inner class UserViewHolder(private val v: UserItemBinding) : RecyclerView.ViewHolder(v.root) {
fun bindUser(position: Int) {
val item = userList[position]
Log.d("ADAPTER", item.toString())
v.user = item
Picasso.get()
.load(item.picture)
.placeholder(R.drawable.ic_launcher_foreground)
.error(R.drawable.ic_launcher_background)
.into(v.picture)
v.userClickInterface = clickListener
v.root.setOnClickListener {
clickListener.onItemClick(item)
}
}
}
UserListFragment:
class UserListFragment : Fragment(), UserClickListener {
private val userViewModel by viewModel<UserViewModel>()
private lateinit var userAdapter: UserRecyclerAdapter
private lateinit var viewDataBinding: FragmentUserListBinding
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
viewDataBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_user_list, container, false)
viewDataBinding.lifecycleOwner = this
return viewDataBinding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclerView.layoutManager = LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
userAdapter = UserRecyclerAdapter(context, this)
recyclerView.adapter = userAdapter
recyclerView.isNestedScrollingEnabled = false
viewDataBinding.viewModel = userViewModel
userViewModel.getUserList()
userViewModel.userList.observe(viewLifecycleOwner, { userList ->
if (userList.isNotEmpty() && userList != null) {
userAdapter.setUsers(userList)
}
})
}
override fun onItemClick(user: UserListItem) {
Log.d("FRAGMENT", user.toString())
userViewModel.getUserFullProfile(user.id)
userViewModel.userFullProfile.observe(viewLifecycleOwner, { userFullProfile ->
Log.d("UFP", userFullProfile.toString())
if (userFullProfile != null) {
(activity as MainActivity).replaceFragment(UserFullProfileFragment.newInstance(userFullProfile),
R.id.fragment_layout, "userFullProfile")
}
})
}
UserFullProfileFragment:
class UserFullProfileFragment : Fragment() {
companion object {
#JvmStatic
fun newInstance(user: UserFullProfile) = UserFullProfileFragment().apply {
arguments = Bundle().apply {
putParcelable("user", user)
}
}
}
private var user: UserFullProfile? = null
private lateinit var mViewDataBinding: FragmentUserFullProfileBinding
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mViewDataBinding.user = user
notify()
Picasso.get()
.load(mViewDataBinding.user?.picture)
.placeholder(R.drawable.ic_launcher_foreground)
.error(R.drawable.ic_launcher_background)
.into(mViewDataBinding.picture)
val dateOfBirth = parseDate(mViewDataBinding.user?.dateOfBirth)
mViewDataBinding.dateOfBirth.text = dateOfBirth
val registerDate = parseDate(mViewDataBinding.user?.registerDate)
mViewDataBinding.registerDate.text = registerDate
}
override fun onAttach(context: Context) {
super.onAttach(context)
user = arguments?.getParcelable("user")
Log.d("APP", user.toString())
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
mViewDataBinding = DataBindingUtil.inflate(inflater,
R.layout.fragment_user_full_profile, container, false)
mViewDataBinding.lifecycleOwner = this
return mViewDataBinding.root
}
Thank you :)
Finally, I found a solution :
I pass the user id argment from UserListFragment to UserFullProfileFragment instead of the current user object and I call the external API to get the current user in the UserFullProfileFragment.
This is the final code:
UserListFragment:
override fun onItemClick(user: UserListItem) {
val action = UserListFragmentDirections.actionUserListFragmentToUserFullProfileFragment(user.id)
findNavController().navigate(action)
}
UserFullProfileFragment:
class UserFullProfileFragment : Fragment() {
private lateinit var userID: String
private var mViewDataBinding: FragmentUserFullProfileBinding? = null
private val binding get() = mViewDataBinding!!
private val userViewModel by viewModel<UserViewModel>()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.viewModel = userViewModel
userID = UserFullProfileFragmentArgs.fromBundle(requireArguments()).userArgs
userViewModel.getUserFullProfile(userID)
userViewModel.userFullProfile.observe(viewLifecycleOwner, { userFullProfile ->
if (userFullProfile != null) {
binding.user = userFullProfile
Picasso.get()
.load(binding.user?.picture)
.placeholder(R.drawable.ic_launcher_foreground)
.error(R.drawable.ic_launcher_background)
.into(binding.picture)
val dateOfBirth = parseDate(binding.user?.dateOfBirth)
binding.dateOfBirth.text = dateOfBirth
val registerDate = parseDate(binding.user?.registerDate)
binding.registerDate.text = registerDate
}
})
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
mViewDataBinding = DataBindingUtil.inflate(inflater,
R.layout.fragment_user_full_profile, container, false)
binding.lifecycleOwner = this
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
mViewDataBinding = null
}
}
I am creating a food ordering app . I am fetching the list of restaurants using volley .
Error:
The restaurant list does not displayed and in the logcat window the following displayed:
E/RecyclerView: No adapter attached; skipping layout
What I have tried to resolve:
used postman to verify volley response,the response is as expected
made sure if the variables were received in the right order
made sure that the array was received in the right format.
I attach the code of the HomeFragment and the adapter file
HomeFragment.class
class HomeFragment : Fragment() {
lateinit var recyclerRestaurant: RecyclerView
lateinit var progressLayout: RelativeLayout
lateinit var progressBar: ProgressBar
lateinit var layoutManager: RecyclerView.LayoutManager
lateinit var recyclerAdapter: RestaurantRecyclerAdapter
var restaurantList = arrayListOf<Restaurant>()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val view = inflater.inflate(R.layout.fragment_home, container, false)
setHasOptionsMenu(true)
recyclerRestaurant = view.findViewById(R.id.recyclerRestaurant)
progressLayout = view.findViewById(R.id.progressLayout)
progressBar = view.findViewById(R.id.progressBar)
layoutManager = LinearLayoutManager(activity)
progressLayout.visibility= View.VISIBLE
val queue = Volley.newRequestQueue(activity as Context)
val url = "http://13.235.250.119/v2/restaurants/fetch_result/"
if (ConnectionManager().checkConnectivity(activity as Context)) {
val jsonObjectRequest = object : JsonObjectRequest(
Request.Method.GET,url , null,
Response.Listener<JSONObject>{
progressLayout.visibility = View.GONE
try {
val data = it.getJSONObject("data")
val success = data.getBoolean("success")
if (success) {
val data = it.getJSONObject("data").getJSONArray("data")
for(i in 0 until data.length()) {
val resObject = data.getJSONObject(i)
val restaurants = Restaurant(
resObject.getString("id").toInt(),
resObject.getString("name"),
resObject.getString("rating"),
resObject.getString("cost_per_person"),
resObject.getString("image_url")
)
restaurantList.add(restaurants)
if(activity != null) {
recyclerAdapter = RestaurantRecyclerAdapter(activity as Context, restaurantList)
val mLayoutManager=LinearLayoutManager(activity)
recyclerRestaurant.layoutManager =mLayoutManager
recyclerRestaurant.adapter = recyclerAdapter
recyclerRestaurant.setHasFixedSize(true)
}
}
}
else {
Toast.makeText(
activity as Context,
"some error has occurred",
Toast.LENGTH_SHORT
).show()
}
}catch (e: JSONException){
e.printStackTrace()
}
},
Response.ErrorListener {
if(activity != null){
Toast.makeText(activity as Context,"Volley error has occurred", Toast.LENGTH_LONG).show() }
}) {
override fun getHeaders(): MutableMap<String, String> {
val headers = HashMap<String, String>()
headers["Content-type"] = "application/json"
headers["token"] = "06f579db533924"
return headers
}
}
queue.add(jsonObjectRequest)
}else{
val dialog = AlertDialog.Builder(activity as Context)
dialog.setTitle("error")
dialog.setMessage("Internet connection not found")
dialog.setPositiveButton("open settings"){ text, listener->
val settingsIntent = Intent(Settings.ACTION_WIRELESS_SETTINGS)
startActivity(settingsIntent)
activity?.finish()
}
dialog.setNegativeButton("exit"){text,listener->
ActivityCompat.finishAffinity(activity as Activity)
}
dialog.create()
dialog.show()
}
return view
}
}
RestaurantRecyclerAdapter.class
class RestaurantRecyclerAdapter(val context:Context, val itemList: ArrayList<Restaurant> ):RecyclerView.Adapter<RestaurantRecyclerAdapter.RestaurantViewHolder>() {
class RestaurantViewHolder(view: View): RecyclerView.ViewHolder(view){
val txtRestaurantName :TextView= view.findViewById(R.id.txtRestaurantName)
val imgRestaurantImage :ImageView = view.findViewById(R.id.imgRestaurantImage)
val txtRating : TextView = view.findViewById(R.id.txtRating)
val txtPerPerson : TextView = view.findViewById(R.id.txtPerPerson)
val llContent : LinearLayout = view.findViewById(R.id.llContent)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RestaurantViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.recycler_single_row,parent,false)
return RestaurantViewHolder(view)
}
override fun getItemCount(): Int {
return itemList.size
}
override fun onBindViewHolder(holder: RestaurantViewHolder, position: Int) {
val restaurant = itemList[position]
holder.txtRestaurantName.text = restaurant.name
holder.txtRating.text = restaurant.rating
holder.txtPerPerson.text = restaurant.cost_per_person
Picasso.get().load(restaurant.image).error(R.drawable.ic_food).into(holder.imgRestaurantImage)
I open the list item, get the data in fetchData(), then I expect that by calling the addTarget() method I will update the current item(name and description). Instead, I create a new one.
Q: How can I update the current one?
class TargetEditFragment : Fragment() {
private var nameEditText: TextInputEditText? = null
private var descriptionEditText: TextInputEditText? = null
private var button: Button? = null
private var databaseReference: DatabaseReference? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.getString(KEY_TARGET_GUID, "")
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_target_add, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
databaseReference = FirebaseDatabase.getInstance().getReference("targets")
setupViews()
fetchData(guid = arguments?.getString(KEY_TARGET_GUID, "") ?: "")
}
private fun setupViews() {
nameEditText = view?.findViewById(R.id.nameEditText)
descriptionEditText = view?.findViewById(R.id.descriptionEditText)
button = view?.findViewById(R.id.addNote)
button?.setOnClickListener { addTarget() }
}
private fun addTarget() {
val name = nameEditText?.text.toString().trim()
val description = descriptionEditText?.text.toString().trim()
if (!TextUtils.isEmpty(name)) {
val id: String = databaseReference?.push()?.key.toString()
val target = Target(guid = id, name = name, description = description)
databaseReference?.child(id)?.setValue(target)
} else Log.d("some", "Enter a name")
}
private fun fetchData(guid: String) {
// Attach a listener to read the data at the target id
databaseReference?.child(guid)?.addValueEventListener(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
val data = dataSnapshot.value as HashMap<String, String>
val name = data["name"] ?: ""
val description = data["description"] ?: ""
if (name.isEmpty()) Log.d("some", "nameIsEmpty")
else {
updateViewsContent(name = name, description = description)
}
}
override fun onCancelled(p0: DatabaseError) {
Log.d("some", "onCancelled")
}
})
}
private fun updateViewsContent(name: String?, description: String?) {
nameEditText?.text = Editable.Factory.getInstance().newEditable(name)
descriptionEditText?.text = Editable.Factory.getInstance().newEditable(description)
}
companion object {
fun newInstance(guid: String): TargetEditFragment =
TargetEditFragment().apply {
arguments = Bundle().apply { putString(KEY_TARGET_GUID, guid) }
}
}
}
There is no way to update an element using the push() method because everytime you call this method a new unique key is generated. In order to perform an update you need to know the key of the element you want to update and use it in your reference. For more informations, please see my answer from the following post:
How to get specific pushedID in Firebase?