In my App, Activity.kt With attached with Adapter.kt and I'm work using RecyclerView in kotlin. In that Adapter.kt in the adapter member onBindViewHolder data parce in AnotherActivity.kt code. But, here problem is that there are no connection between two Activities (Activity.kt and AnotherActivity.kt). So, My problem is that how to the parce data between two activity without using Intent???
Title: Adapter.kt
class ChatAdapter (val chatList: ArrayList<ChatMessage>) : RecyclerView.Adapter<ChatAdapter.ViewHolder>() {
override fun onCreateViewHolder(p0: ViewGroup, p1: Int): ChatAdapter.ViewHolder {
val v = LayoutInflater.from(p0.context).inflate(R.layout.chat_sort, p0, false)
return ViewHolder(v)
}
override fun getItemCount(): Int {
return chatList.size
}
override fun onBindViewHolder(p0: ChatAdapter.ViewHolder, p1: Int) {
val chat: ChatMessage = chatList[p1]
p0.msg.text = chat.msgText /// Problem with this data is send in AnotherActivity.kt code
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val msg = itemView.findViewById(R.id.tv_msg_from_user) as TextView
}
There are not gone or start or launch AnotherActivity.kt . Only transfer data in the Adapter.kt. to AnotherActivity.kt
You could create a application class having a getInfo() function in companion object function.
class MyApp : Application() {
companion object {
var info: String? = null
fun getInfo(): String {
return info
}
fun setInfo(info1: String) {
info = info1
}
}
}
You can simply get it using MyApp.getInfo()
Related
I'm new to kotlin and I could not find related solutions.
What I want to do is get the data from api(amount and currency) and show it onclick.
I was able to loop data but I don't know how to unloop.
The response from api is this:
{
"data": {
"amount": 825,
"currency": "hkd"
}
}
My Model:
data class MainData(
var data: AmountData
)
data class AmountData(
val amount: Int,
val currency: String,
)
My ApiService:
interface ApiService {
#GET("posts")
fun getPosts(): Call<MutableList<PostModel>>
#GET("checkout/vend/CLIENT_ID/payment/request")
fun paymentRequest(): Call<MainData>
}
My Adapter:
class PaymentAdapter(private val mainData: MainData): RecyclerView.Adapter<PaymentViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PaymentViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.card_post, parent, false)
return PaymentViewHolder(view)
}
override fun onBindViewHolder(holder: PaymentViewHolder, position: Int) {
return holder.bindView(mainData) // I don't even know how to bind the data
}
override fun getItemCount(): Int {
return mainData.data.amount // This is also incorrect but I don't know what to do
}
}
class PaymentViewHolder(itemView: View): RecyclerView.ViewHolder(itemView){
private val tvAmount: TextView = itemView.findViewById(R.id.tvAmount)
private val tvCurrency: TextView = itemView.findViewById(R.id.tvCurrency)
fun bindView(mainData: MainData){
tvAmount.text = mainData.data.amount.toString()
tvCurrency.text = mainData.data.currency
}
}
This is the result so far.
because you only have 1 item always you could just do
override fun getItemCount(): Int {
return 1
}
And it might give already exactly what you want
Though, it really is unnecessary to use a RecyclerView for this then. I would remove the RecyclerView and just add two TextViews or something.
I marked the parts that were added (added to code) after the moment
when the application was working, the data was successfully downloaded
from the database. I may be mistakenly trying to pass this information
to another screen. I tried to find a video that connects to the
database and forwards that data of recicler on another screen, but
without success, or they are in Java, which I understand less.
MySecondActivity
class BookDescription : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_book_description)
var books = intent.getSerializableExtra("noti") as Book //added to code
Glide.with(this).load(books.imageUrl).into(bookImg2)// added to code
nameTxt2.text = books.name //added to code
autorTxt2.text = books.writer //added to code
}
}
MainActivity
class MainActivity : AppCompatActivity() {
private lateinit var adapter : Adapter
private val viewModel by lazy { ViewModelProviders.of(this).get(MainViewModel::class.java)}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setUpRecyclerView()
}
private fun setUpRecyclerView(){
adapter = Adapter(this){
startBookDescription()
}
recycle.layoutManager = GridLayoutManager(this, 2)
recycle.adapter = adapter
observerData()
}
fun observerData(){
viewModel.fetchUserData().observe(this,Observer{
adapter.setListdata(it)
adapter.notifyDataSetChanged()
})
}
private fun startBookDescription(){
val intent = Intent (this, BookDescription::class.java )
startActivity(intent)
}
}
Class Adapter with inner class Holder
class Adapter(private val context: Context,
private val onItemCliked: () -> Unit ) : RecyclerView.Adapter<Adapter.Holder>() {
private var datalist = mutableListOf<Book>()
fun setListdata(data: MutableList<Book>){
datalist = data
}
inner class Holder(itemView : View) : RecyclerView.ViewHolder(itemView){
fun bindView(book: Book, onItemClicked: () -> Unit){
Glide.with(context).load(book.imageUrl).into(itemView.bookImg)
itemView.nameTxt.text = book.name
itemView.autorTxt.text= book.writer
itemView.setOnClickListener { onItemClicked.invoke() }
itemView.bookImg.setOnClickListener(View.OnClickListener { //added
val intent = Intent(context, BookDescription::class.java)//added to code
intent.putExtra("noti", book)//added to code
context.startActivity(intent)//added to code
})
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
val view = LayoutInflater.from(context).inflate(R.layout.book_format, parent,
false )
return Holder(view)
}
override fun onBindViewHolder(holder: Holder, position: Int) {
val book = datalist[position]
holder.bindView(book, onItemCliked)
}
override fun getItemCount(): Int {
return if (datalist.size> 0){
datalist.size
}else{
0
}
}
}
The problem is here:
intent.putExtra("noti", book)
The book variable is of type Book, which is apparently neither a Parcelable or Serializable class. You must implement one of these two interfaces in the Book class in order to add it to an Intent or Bundle.
Assuming Book is made up of simple data types (String, Int, etc), then you can use the #Parcelize annotation to easily implement Parcelable. More here: https://developer.android.com/kotlin/parcelize
In your bindView() method, you have this block of code:
val intent = Intent(context, BookDescription::class.java)//added to code
intent.putExtra("noti", book)//added to code
context.startActivity(intent)//added to code
})
However, you don't actually do anything with this Intent; you start your activity from another place:
private fun startBookDescription(){
val intent = Intent (this, BookDescription::class.java )
startActivity(intent)
}
You will have to pass the Book instance to this method (via invoke(book)). This will require a corresponding type change to the click listener parameter of your adapter.
I am doing a school project.
I have a list with Doses, so I need to fetch data en set text one by one.
Right now I'm getting:
kotlin.UninitializedPropertyAccessException: lateinit property medicine has not been initialized.
So I need to wait till the first item is fetched and set before continuing to next item.
can you help me?
class ClientDoseListAdapter(private val doses: List<Dose>) : RecyclerView.Adapter<ClientDoseListAdapter.ViewHolder>() {
private lateinit var medicine : Medicine
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.client_dose_listitem, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = doses[position]
runBlocking {
displayMedicine(item.medicine)
}
holder.med_name.text = medicine.name
holder.dose_amount.text = item.amount.toString()
}
private suspend fun displayMedicine(id: Int) {
fetchMedicine(id)
}
override fun getItemCount(): Int = doses.size
inner class ViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView),
LayoutContainer
private fun fetchMedicine(id: Int) {
service.getMedicine(id, "Bearer ${ClienOverzichtFragment.auth}")
.enqueue(object : Callback<List<Medicine>> {
override fun onResponse(call: Call<List<Medicine>>, response: Response<List<Medicine>>) {
if (response.code() == 200) {
val temp = response.body()!!
medicine = temp[0]
Log.v("SHIT", medicine.name)
} else {
Log.v("SHIT", response.code().toString())
//TODO
}
}
override fun onFailure(call: Call<List<Medicine>>, t: Throwable) {
Log.v("SHIT", "FAILED : "+t.message)
}
})
}
}
Move your service call out of the Recycler (best into a ViewModel, but can call from Activity or using any other pattern - the main thing, shouldn't be part of the Recycler) and pass the data, when it's received, into the Recycler.
Your ClientDoseListAdapter to accept medicine:
class ClientDoseListAdapter(private val doses: List<Dose>, private val medicine: Medicine)
In your activity, initiate and a call for medicine and observe it - when the data arrives, pass it to the adapter. Assuming you use a view model your code in Activity would look something like this:
viewModel.getMedicine().observe(
this,
Observer<Medicine> { medicine ->
//assuming doses come from somewhere else
adapter = ClientDoseListAdapter(doses, medicine, this)
clientDoseRecyclerView.adapter = adapter
}
)
I am trying to display navigation bar title in my TestProjectList class activity but the value is empty so, I am not able to see the Navigation bar tile. I am not sure why its showing empty Value. Your help is appreciated.
Model Class:
class TestProject(val name: String,val location: String)
Main Class:
private class ItemDetailAdapter(val TestProjectList:Array<TestProject>): RecyclerView.Adapter<ItemDetailViewHolder>()
{
override fun onBindViewHolder(p0: ItemDetailViewHolder, p1: Int) {
val TestProject=TestProjectList.get(p1)
p0?.customView?.TestProjectName?.text=TestProject.name
val TestProjectPicture=p0?.customView?.itemPicture
Picasso.get().load(TestProject.location).into(TestProjectPicture)
}
override fun getItemCount(): Int {
return TestProjectList.size
}
override fun onCreateViewHolder(p0: ViewGroup, p1: Int): ItemDetailViewHolder {
val layoutInflater=LayoutInflater.from(p0?.context)
val customView=layoutInflater.inflate(R.layout.items_details,p0,false)
return ItemDetailViewHolder(customView)
}
}
class ItemDetailViewHolder(val customView:View,var Title: TestProject?=null):RecyclerView.ViewHolder(customView)
{
companion object {
val ITEM_TITLE_KEY="TestProject"
}
init {
customView.setOnClickListener {
val intent= Intent(customView.context,TestProjectMenuList::class.java)
intent.putExtra(ITEM_TITLE_KEY,Title?.name)
print("Printting Title :$Title?.name")
println("Hello Test $ITEM_TITLE_KEY")
customView.context.startActivity(intent)
println("Test")
}
}
TestProjectList Class:
val navBarTitle=intent.getStringExtra(MainClass.ItemDetailViewHolder.ITEM_TITLE_KEY)
supportActionBar?.title=navBarTitle
When you are creating your viewholder in the adapter return ItemDetailViewHolder(customView) you aren't passing any value for the parameter Title. You aren't setting it up latter either, but you are populating the intent with intent.putExtra(ITEM_TITLE_KEY,Title?.name). In this case the value you will always retrieve from the intent will be null.
Model Class:
class TestProject(val name: String,val location: String)
Main Class:
private class ItemDetailAdapter(val TestProjectList:Array<TestProject>): RecyclerView.Adapter<ItemDetailViewHolder>()
{
override fun onBindViewHolder(p0: ItemDetailViewHolder, p1: Int) {
val TestProject=TestProjectList.get(p1)
p0?.customView?.TestProjectName?.text=TestProject.name
val TestProjectPicture=p0?.customView?.itemPicture
Picasso.get().load(TestProject.location).into(TestProjectPicture)
//Below code solved the Title Problem
p0?.Title=TestProject
}
override fun getItemCount(): Int {
return TestProjectList.size
}
override fun onCreateViewHolder(p0: ViewGroup, p1: Int): ItemDetailViewHolder {
val layoutInflater=LayoutInflater.from(p0?.context)
val customView=layoutInflater.inflate(R.layout.items_details,p0,false)
return ItemDetailViewHolder(customView)
}
}
class ItemDetailViewHolder(val customView:View,var Title: TestProject?=null):RecyclerView.ViewHolder(customView)
{
companion object {
val ITEM_TITLE_KEY="TestProject"
}
init {
customView.setOnClickListener {
val intent= Intent(customView.context,TestProjectMenuList::class.java)
intent.putExtra(ITEM_TITLE_KEY,Title?.name)
print("Printting Title :$Title?.name")
println("Hello Test $ITEM_TITLE_KEY")
customView.context.startActivity(intent)
println("Test")
}
}
TestProjectList Class:
val navBarTitle=intent.getStringExtra(MainClass.ItemDetailViewHolder.ITEM_TITLE_KEY)
supportActionBar?.title=navBarTitle
I am trying to implement a Interactive Console for one of the Android application. I am using ChatKit for this. Apart from the existing message layouts, I want to use a custom message type,layout & view holder.
This is what I did.
val CONTENT_TYPE_CARD_LIST= "5".toByte()
val holders = MessageHolders().registerContentType(CONTENT_TYPE_CARD_LIST,
CardListViewHolder::class.java,R.layout.card_list_layout,
CardListViewHolder::class.java,R.layout.card_list_layout,
object : MessageHolders.ContentChecker<Message>{
override fun hasContentFor(message: Message?, type: Byte): Boolean {
if (type.toString().equals("5"))
return true
return false
}
})
Here is the CardListViewHolder.kt file
class CardListViewHolder(itemView: View?) : MessageHolders.BaseMessageViewHolder<Message>(itemView) {
var cardsListView : RecyclerView
init {
cardsListView = itemView?.findViewById(R.id.cardList)!!
}
override fun onBind(data: Message?) {
print("Checking")
}
class CardListAdapter : RecyclerView.Adapter<CardItemViewHolder>() {
var listItems : Array<CardItem> = emptyArray()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CardItemViewHolder {
return CardItemViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.card_item,parent,false))
}
override fun getItemCount(): Int {
return listItems.size
}
override fun onBindViewHolder(holder: CardItemViewHolder, position: Int) {
holder.cardTitle?.text = listItems[position].cardTitle
holder.cardSummary?.text = listItems[position].cardSummary
Picasso.get().load(Uri.parse(listItems[position].cardImageUrl)).into(holder.cardIcon)
}
}
class CardItemViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView) {
var cardTitle : TextView ?= null
var cardSummary : TextView ?= null
var cardIcon : ImageView ?= null
init {
cardTitle = itemView?.findViewById(R.id.cardTitle)
cardSummary = itemView?.findViewById(R.id.cardSummary)
cardIcon = itemView?.findViewById(R.id.cardIcon)
}
}
}
But, now this is not loading the existing text MessageHolders/Layouts. I want to use the existing message cell types along with this extra Carousal kind of message layout.
Did I do something wrong here ? Why other existing content types not working ?