I get null on object reference. I have a default value set(not sure if this has an effect). My DataState is in a Arraylist which is shown in a Recyclerview. Datastate is changed when a button is clicked and reflect on a textview.
My datestate class:
enum class DataState {
Unselected,
Success,
Failure
}
My Arraylist:
class Tripsheetlist (var videos: ArrayList<DataModel>)
class DataModel(
var Tripsheet: Int,
var WOrder: Int,
var DElNote: Int,
var name: String,
var Weight: Int,
var tvdone: String,
var Drivers: String,
var state: DataState = DataState.Unselected
)
My Adapter:
if ( rowPos != 0){
val modal = tripsheetlist.videos[rowPos -1]
holder.txttvdone.apply {
setBackgroundResource(when (modal.state) {
DataState.Unselected -> android.R.color.transparent
DataState.Success -> R.color.green
DataState.Failure -> R.color.orange
})
text = when (modal.state) {
DataState.Unselected -> ""
DataState.Success -> "✓"
DataState.Failure -> "x"
//this is where I add code to export data through api maybe add it in the datastate set where it is success and Failure
}
}
holder.apply {
txtbutton1.setOnClickListener {
Log.e("Clicked", "Successful delivery")
//this is where I add code to export data through api
modal.state = DataState.Success
notifyDataSetChanged()
}
txtbutton2.setOnClickListener {
Log.e("Clicked", "Exception on delivery")
modal.state = DataState.Failure
notifyDataSetChanged()
}
}}
I get the error on the line setBackgroundResource(when (modal.state) {
Error :
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.dispatch.tripsheet, PID: 12935
java.lang.NullPointerException: Attempt to invoke virtual method 'int com.dispatch.tripsheet.DataState.ordinal()' on a null object reference
at com.dispatch.tripsheet.TableViewAdapter.onBindViewHolder(TableViewAdapter.kt:162)
at com.dispatch.tripsheet.TableViewAdapter.onBindViewHolder(TableViewAdapter.kt:12)
at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7254)
at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7337)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6194)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6460)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6300)
Below will be my full adapter and Main class.
Adapter:
package com.dispatch.tripsheet
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.*
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.table_list_item.view.*
class TableViewAdapter(
var tripsheetlist: Tripsheetlist,
val driver: String,
var tvHeader: TextView,
val spnDriver: Spinner,
var adapter: ArrayAdapter<String>,
) : RecyclerView.Adapter<TableViewAdapter.RowViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RowViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.table_list_item, parent, false)
var i: Int = 0
var totT: Int = 1
var a: Int = 0
var b: Int = 0
var c: Int = 0
var l: Int = tripsheetlist.videos.size -1
while (i <= l){
if (driver == tripsheetlist.videos[i].Drivers) {
if (a == 0){
a = tripsheetlist.videos[i].Tripsheet}
totT = totT
if(a != tripsheetlist.videos[i].Tripsheet) {
if (b == 0){
b = tripsheetlist.videos[i].Tripsheet}
if ( totT != 3){
totT = 2}
if(b != tripsheetlist.videos[i].Tripsheet) {
c = tripsheetlist.videos[i].Tripsheet
totT = 3
}
}
}
i++
}
when (totT)
{
1 -> tvHeader.setText("Vulcan Steel Trip Sheet: " +a)
2-> tvHeader.setText("Vulcan Steel Trip Sheet: " + a + " & " + b )
3-> tvHeader.setText("Vulcan Steel Trip Sheet: " + a + " & " + b + " & " + c)
else -> tvHeader.setText("Vulcan Steel Trip Sheets")
}
var h =0
// val driverList = tripsheetlist?.videos.distinctBy { it.Drivers }
// while (h <= driverList.size){
// adapter.add(driverList[h].Drivers.toString())
// h++
// }
//used for testing until we have driver data
while (h <= 4){
adapter.add("driverList[h].Drivers.toString()"+h)
h++
}
spnDriver.adapter = adapter
return RowViewHolder(itemView) }
private fun updateData(data: ArrayList<DataModel>) {
tripsheetlist.videos = data
notifyDataSetChanged()
}
override fun getItemCount(): Int { return tripsheetlist.videos.size + 1 // one more to add header row
}
override fun onBindViewHolder(holder: RowViewHolder, position: Int) {
val rowPos = holder.adapterPosition
if (rowPos == 0) {
holder.itemView.apply {
setHeaderBg(txtWOrder)
setHeaderBg(txtDElNote)
setHeaderBg(txtCompany)
setHeaderBg(txtWeight)
setHeaderBg(txttvdone)
txtWOrder.text = "WOrder"
txtDElNote.text = "DElNote"
txtCompany.text = "Compan"
txtWeight.text = "Weight"
txttvdone.text = "?"
}
} else {
val modal = tripsheetlist.videos[rowPos -1]
holder.itemView.apply {
setContentBg(txtWOrder)
setContentBg(txtDElNote)
setContentBg(txtCompany)
setContentBg(txtWeight)
txtWOrder.text = modal.WOrder.toString()
txtDElNote.text = modal.DElNote.toString()
txtCompany.text = modal.name //company
txtWeight.text = modal.Weight.toString()
// used when we have driver data
// if (modal.Drivers == driver) {
// txtWOrder.text = modal.WOrder.toString()
// txtDElNote.text = modal.DElNote.toString()
// txtCompany.text = modal.name
// txtWeight.text = modal.Weight.toString()
//
// }
}
}
//used for testing to look in concsole for responeses - all return null
// println(tripsheetlist.videos[rowPos ].name) //name needs to be chagned to company
// println("where we need to see the state")
// println("-1")
// println(tripsheetlist.videos[rowPos ].state)
// println("0")
// println(tripsheetlist.videos[0].state)
// println("+1")
// println(tripsheetlist.videos[1 ].state)
var p = tripsheetlist.videos[1].state
println("state")
println(p)
if ( rowPos != 0){
val modal = tripsheetlist.videos[rowPos -1]
holder.txttvdone.apply {
setBackgroundResource(when (modal.state) {
DataState.Unselected -> android.R.color.transparent
DataState.Success -> R.color.green
DataState.Failure -> R.color.orange
})
text = when (modal.state) {
DataState.Unselected -> ""
DataState.Success -> "✓"
DataState.Failure -> "x"
//this is where I add code to export data through api maybe add it in the datastate set where it is success and Failure
}
}
holder.apply {
txtbutton1.setOnClickListener {
Log.e("Clicked", "Successful delivery")
//this is where I add code to export data through api
modal.state = DataState.Success
notifyDataSetChanged()
}
txtbutton2.setOnClickListener {
Log.e("Clicked", "Exception on delivery")
modal.state = DataState.Failure
notifyDataSetChanged()
}
}}
}
class RowViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
val txttvdone:TextView = itemView.findViewById<TextView>(R.id.txttvdone)
val txtbutton1:Button = itemView.findViewById<Button>(R.id.txtbutton1)
val txtbutton2:Button = itemView.findViewById<Button>(R.id.txtbutton2)
}
private fun setHeaderBg(view: View) {
view.setBackgroundResource(R.drawable.table_header_cell_bg)
}
private fun setContentBg(view: View) {
view.setBackgroundResource(R.drawable.table_content_cell_bg)
}
}
Main class:
package com.dispatch.tripsheet
import android.os.Bundle
import android.view.View
import android.widget.*
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.gson.GsonBuilder
import kotlinx.android.synthetic.main.activity_main.*
import okhttp3.*
import java.io.IOException
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
recyclerViewTripsheetlist.layoutManager = LinearLayoutManager(this)
val spnDriver: Spinner = findViewById(R.id.spnDriver)
var adapter = ArrayAdapter<String>(this, androidx.appcompat.R.layout.support_simple_spinner_dropdown_item)
fetchJson( adapter, spnDriver)
}
private fun fetchJson(adapter: ArrayAdapter<String>, spnDriver: Spinner){
println("Attempting to Fetch JSON")
val url = "https://api.letsbuildthatapp.com/youtube/home_feed"
val request = Request.Builder().url(url).build()
val client = OkHttpClient()
client.newCall(request).enqueue(object: Callback {
override fun onFailure(call: Call, e: IOException) {
println("Failed to execute request") }
override fun onResponse(call: Call, response: Response) {
val body = response.body?.string()
println(body)
val gson = GsonBuilder().create()
val tripsheetlist = gson.fromJson(body, Tripsheetlist::class.java)
//remove the following later
tripsheetlist.videos.apply {
add(DataModel(190617, 182832, 1, "100",20, "Delivery not done",""))
add(DataModel(190616, 182833, 2, "100",10, "Exceptions",""))
add(DataModel(190616, 182832, 3, "100",100, "50%",""))
}
weightsum(tvTotalweight, tripsheetlist)
totaldelNotes(tvTotaldelv,tripsheetlist)
var driver : String = Spinner(tripsheetlist, adapter)
runOnUiThread {
recyclerViewTripsheetlist.adapter = TableViewAdapter(tripsheetlist, driver, tvHeader, spnDriver, adapter)
}
}
})
}
private fun Spinner(tripsheetlist: Tripsheetlist, adapter: ArrayAdapter<String>): String {
var driver : String = ""
var item : String = ""
var rowTot : Int = tripsheetlist?.videos.size
spnDriver.onItemSelectedListener = object : AdapterView.OnItemSelectedListener{
override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
var rowPos : Int = 0
while (rowPos != rowTot){
//check which one of the following works
// item = tripsheetlist.videos[p2].Drivers.toString()
item = p2.toString()
rowPos = rowTot
}
Toast.makeText(this#MainActivity, "Driver $item selected", Toast.LENGTH_SHORT).show()
driver = item
}
override fun onNothingSelected(p0: AdapterView<*>?) {
driver = ""
//empty
}
}
return driver
}
private fun totaldelNotes(tvTotaldelv: TextView, tripsheetlist: Tripsheetlist) {
var totnotes :Int = tripsheetlist.videos.size
tvTotaldelv.setText("Total Delivery Notes: " +totnotes) }
private fun weightsum(tvTotalweight: TextView, tripsheetlist: Tripsheetlist) {
var totweight: Int = 0
var sum: Int = 0
for (i in 0 until tripsheetlist.videos.size) {
sum += tripsheetlist.videos[i].Weight }
totweight = sum
tvTotalweight.setText("Total Weight: " + totweight + "kg")
}
//not used
fun limitDropDownHeight(spinner: Spinner){
val popup = Spinner::class.java.getDeclaredField( "mPopup")
popup.isAccessible = true
val popupWindow = popup.get(spinner)as ListPopupWindow
popupWindow.height = (200 * resources.displayMetrics.density).toInt()
}
}
Related
i want to update the value of my textview that is in the PosActivity when the button in MyAdapter is click ( to increase/decrease the quantity and to delete the card from recycler view). and i can't find anything on how to do it.
here is what i tried.
in MyAdapter :
package com.mycodlabs.pos.ui.sale.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.mycodlabs.pos.R
import com.mycodlabs.pos.domain.inventory.ProductModel
import kotlinx.android.synthetic.main.pos_item_card.view.*
import java.math.BigDecimal
class MyAdapter(mUx: Context, var selectedItems: ArrayList<ProductModel>) : RecyclerView.Adapter<MyAdapter.ViewHolder>() {
val mUx = mUx
// var quantity = 1
var totalPrice = BigDecimal.ZERO
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var pclose = itemView.removeItempos
var pname = itemView.pos_name
var pprice = itemView.pos_price
var pqty = itemView.pos_qty
var pminus = itemView.cart_minus_img
var pplus = itemView.cart_plus_img
// val pimage = itemView.pos_image
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.pos_item_card, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val pos: ProductModel = selectedItems[position]
holder.pname.text = pos.name
holder.pprice.text = pos.unitPrice.toString()
holder.pqty.text = pos.quantity.toString()
// holder.pimage.= pos.image
holder.pclose.setOnClickListener {
val username = pos.name
var price = pos.unitPrice
totalPrice -= price
selectedItems.removeAt(position)
notifyDataSetChanged()
notifyItemRangeChanged(position, selectedItems.size)
// Toast.makeText(mUx, "User $username Deleted", Toast.LENGTH_SHORT).show()
}
holder.pminus.setOnClickListener {
if(pos.quantity == 1 ){
// Toast.makeText(mUx,"Can't go any lower", Toast.LENGTH_SHORT).show()
}else {
pos.quantity -= 1
notifyItemChanged(position)
}
}
holder.pplus.setOnClickListener {
pos.quantity += 1
notifyItemChanged(position)
}
}
fun grandTotal(items: ArrayList<ProductModel>): BigDecimal {
totalPrice = BigDecimal.ZERO
for (i in items.indices) {
totalPrice += items[i].unitPrice.multiply(items[i].quantity.toBigDecimal())
}
return totalPrice
}
fun clearData() {
selectedItems.clear()
notifyDataSetChanged()
}
override fun getItemCount() = selectedItems.size
}
and in the Activity:
package com.mycodlabs.pos.ui
import android.os.Bundle
import android.view.View
import android.widget.*
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.mycodlabs.pos.R
import com.mycodlabs.pos.db.AndroidDatabase
import com.mycodlabs.pos.db.DatabaseTables
import com.mycodlabs.pos.db.inventory.InventoryDbo
import com.mycodlabs.pos.db.sale.SalesLinesDao
import com.mycodlabs.pos.domain.inventory.ProductModel
import com.mycodlabs.pos.ui.sale.adapter.MyAdapter
import kotlinx.android.synthetic.main.activity_pos.*
import kotlinx.android.synthetic.main.adapter_available_promotions.*
import kotlinx.android.synthetic.main.dialog_paymentsuccession.view.*
import kotlinx.android.synthetic.main.dialog_saleedit.*
import kotlinx.android.synthetic.main.layout_addcategory.*
import kotlinx.android.synthetic.main.layout_sale.*
import kotlinx.android.synthetic.main.listview_stock.*
import kotlinx.android.synthetic.main.pos_bottom_sheet.*
import kotlinx.android.synthetic.main.pos_item_card.*
class PosActivity : AppCompatActivity() {
private lateinit var bottomSheetBehavior: BottomSheetBehavior<LinearLayout>
private lateinit var productNames: ArrayList<String>
private lateinit var recyclerView: RecyclerView
private lateinit var db: SalesLinesDao
//// Create an empty list to store the selected items
var selectedItems = ArrayList<ProductModel>()
//// Create an adapter for the RecyclerView
val adapter = MyAdapter(this,selectedItems)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_pos)
// for Back button
back.setOnClickListener {
finish()
}
check_out_Pos.setOnClickListener{
// val pos = ProductModel()
//
// db = SalesLinesDbo(this)
//
// pos.name = pos_name.text.toString()
//
// db.addLineItem(pos.id, LineItemModel())
adapter.clearData()
}
// val autoCompleteTextView = findViewById<AutoCompleteTextView>(R.id.searchBoxPos)
// autoCompleteTextView.threshold = 0
// val suggestions =InventoryDbo.getInstance(applicationContext).allProduct
// var NameArray=suggestions.toList().filter { t -> t.name.contains(autoCompleteTextView)}.toList().map { m->m.name }
// val arrayAdapter = ArrayAdapter(this, android.R.layout.simple_expandable_list_item_2 ,NameArray)
// autoCompleteTextView.setAdapter(arrayAdapter)
// Auto Complete Textview filtering from Product table colm "productName"
val autoCompleteTextView = findViewById<AutoCompleteTextView>(R.id.searchBoxPos)
val productNames = ArrayList<String>()
val dbHelper = AndroidDatabase(this)
val db = dbHelper.readableDatabase
val cursor = db.rawQuery(
"SELECT DISTINCT ${InventoryDbo.colm_productName} FROM ${DatabaseTables.TABLE_PRODUCT} WHERE ${InventoryDbo.colm_productName} like '%%'",
null
)
if (cursor.moveToFirst()) {
do {
productNames.add(cursor.getString(cursor.getColumnIndex(InventoryDbo.colm_productName)))
} while (cursor.moveToNext())
}
cursor.close()
db.close()
val adapterr = ArrayAdapter(this, android.R.layout.simple_dropdown_item_1line, productNames)
autoCompleteTextView.setAdapter(adapterr)
// //// Auto Complete suggestion item display in recyclerview on select
// // Create the RecyclerView
val recyclerView = findViewById<RecyclerView>(R.id.sale_List_Pos)
//// Create a layout manager for the RecyclerView
val layoutManager = LinearLayoutManager(this)
recyclerView.layoutManager = layoutManager
recyclerView.adapter = adapter
// Set an item click listener for the AutoCompleteTextView
searchBoxPos.setOnItemClickListener { _, _, position, _ ->
// Get the selected product name and product from the list
val selectedItem = autoCompleteTextView.adapter.getItem(position).toString()
// val selectedProductName = productNames[position]
val selectedProduct = InventoryDbo.getInstance(applicationContext).getPosProductByName(selectedItem).first()
//InventoryDbo.getProductByName(selectedProductName)
// Add the selected product to the selected items list
selectedItems.add(selectedProduct)
// Notify the adapter that the data has changed
adapter.notifyDataSetChanged()
// Clear the focus and text from the AutoCompleteTextView
searchBoxPos.clearFocus()
searchBoxPos.setText("")
total_items_Pos.text = adapter.grandTotal(selectedItems).toString()
}
//for the bottomsheet
bottomSheetBehavior = BottomSheetBehavior.from<LinearLayout>(std_btm_sht)
bottomSheetBehavior.setBottomSheetCallback(object :
BottomSheetBehavior.BottomSheetCallback() {
override fun onStateChanged(bottomSheet: View, state: Int) {
print(state)
when (state) {
BottomSheetBehavior.STATE_HIDDEN -> {
}
BottomSheetBehavior.STATE_EXPANDED -> {
total_items_Pos.text = adapter.grandTotal(selectedItems).toString()
}
BottomSheetBehavior.STATE_COLLAPSED -> {
total_items_Pos.text = adapter.grandTotal(selectedItems).toString()
}
BottomSheetBehavior.STATE_DRAGGING -> {
total_items_Pos.text = adapter.grandTotal(selectedItems).toString()
}
BottomSheetBehavior.STATE_SETTLING -> {
total_items_Pos.text = adapter.grandTotal(selectedItems).toString()
}
BottomSheetBehavior.STATE_HALF_EXPANDED -> {
total_items_Pos.text = adapter.grandTotal(selectedItems).toString()
}
}
}
override fun onSlide(bottomSheet: View, slideOffset: Float) {
}
})
}
}
i hope you can help me solve this because it was bugging me all day and i couldn't find anything about it
I'll post the changes for the plus button, you can then repeat it for the others. Mind that this is just an example, as I don't know in what way you'd like to update the text or what's the actual name of your TextView.
class MyAdapter(
mUx: Context,
var selectedItems: ArrayList<ProductModel>,
val plusLambda: (String) -> Unit // <------
) : RecyclerView.Adapter<MyAdapter.ViewHolder>() {
...
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val pos: ProductModel = selectedItems[position]
...
holder.pplus.setOnClickListener {
pos.quantity += 1
plusLambda("The new quantity is: ${ pos.quantity }") // <------
notifyItemChanged(position)
}
...
class PosActivity : AppCompatActivity() {
...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_pos)
...
val adapterr = ArrayAdapter(this,
android.R.layout.simple_dropdown_item_1line,
productNames) {
someTextView.text = it // <------
}
autoCompleteTextView.setAdapter(adapterr)
...
Of course, you can use just one lambda for all buttons if all you want to do is to change the text of the TextView.
I got blocked for this problem, Api will call and get the objects from the response and it will display on the recyclerview. But it is not showing,
fetchProductCategories will do the api call.
prepareProducts will handle the fetched from fetchProductCategories
Fragment:
#AndroidEntryPoint
class ProductsWelcomeFragment : BaseProductsFragment<ProductsWelcomeViewModel, ProductsWelcomeFragmentBinding>() {
private val TAG = "ProductsWelcomeFragment"
#Inject
lateinit var animationQueue: AnimationQueue
override fun getViewModelClass(): KClass<ProductsWelcomeViewModel> = ProductsWelcomeViewModel::class
override fun getContentViewRes(): Int = R.layout.products_welcome_fragment
private val cordovaViewModel: CordovaViewModel by activityViewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
/**
* Initialize only once when everytime accessing products screen.
* */
sharedViewModel.initialSetUpRequest()
viewModel.fetchProductCategories()
}
override fun onBindView() {
with(dataBinding) {
viewModel = this#ProductsWelcomeFragment.viewModel
title = getString(R.string.products_screen_welcome_header)
recyclerViewProducts.configure()
executePendingBindings()
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.productCategoriesLiveData.observe(viewLifecycleOwner) {
Log.i(TAG, it.toString())
viewModel.items.observe(viewLifecycleOwner) {
viewModel.prepareProducts()
}
}
viewModel.showProgress.observe(viewLifecycleOwner) {}
viewModel.failedAtRetrievingData.observe(viewLifecycleOwner) {
// showErrorScreen(true)
}
}
private fun RecyclerView.configure() {
with(dataBinding.recyclerViewProducts) {
addItemBindings(SectionHeaderItemViewBinder)
addItemBindings(SpaceItemViewDtoBinder)
addItemBindings(getListButtonItemViewBinder(ProductItem.NormalProduct::dto, ::onProductItemClick))
addItemBindings(getListBigtileItemViewBinder(ProductItem.FeaturedProduct::dto, ::onProductItemClick))
}
}
private fun onProductItemClick(product: ProductItem.NormalProduct) {
when (product.id) {
else -> { // TODO : )}
}
// TODO : implement move to another screen
}
private fun onProductItemClick(product: ProductItem.FeaturedProduct) {
// TODO : implement move to another screen
}
private fun showErrorScreen(isDataRetrievalError: Boolean) {
val dismissAction = ErrorHandlingAction(
getString(R.string.native_done),
null,
null,
ButtonType.PRIMARY
) { dismissDialog ->
dismissDialog.dismiss()
if (isDataRetrievalError) {
findNavController().popBackStack()
}
}
DialogFactory().showBottomDialog(
fragmentManager = parentFragmentManager,
window = requireActivity().window,
title = getString(R.string.native_error_title),
description = getString(R.string.online_identity_something_went_wrong_error_description),
iconId = R.drawable.ic_error_thick_exclamation_icon,
errorHandlingActions = arrayOf(dismissAction),
isHtmlDescription = true
)
}
private fun openCordovaScreen(destination: CordovaPage) {
cordovaViewModel.requestPage(destination)
findNavController().popBackStack(R.id.homeScreenMainFragment, false)
}
}
ViewModel:
#HiltViewModel
class ProductsWelcomeViewModel #Inject constructor(
private val productsRepository: ProductsRepository
) : BaseRequestViewModel(), ViewModelWithItems {
private val TAG = "ProductsWelcomeViewModel"
private val _failedAtRetrievingData = SingleLiveEvent<Boolean>()
val failedAtRetrievingData: LiveData<Boolean> = _failedAtRetrievingData
private val _showProgress = MutableLiveData<Boolean>()
val showProgress: LiveData<Boolean> = _showProgress
private val onProductCategories: SingleLiveEvent<ProductBasketsCategoriesModel?> = SingleLiveEvent()
val productCategoriesLiveData: LiveData<ProductBasketsCategoriesModel?> = onProductCategories
private val _items: MutableLiveData<List<Any>> = MutableLiveData()
override val items: LiveData<List<Any>> = _items
fun fetchProductCategories() {
viewModelScope.launch {
request({ productsRepository.getProductCategories() },
success = { response -> onProductCategories.value = response },
failure = { })
}
}
fun prepareProducts() {
_items.value = mutableListOf<Any>().apply {
productCategoriesLiveData.value?.embedded?.categories?.filter { categories ->
categories.isFeatured == true }?.let { filteredCategories ->
add(HeaderItem(ListSectionHeaderItemViewDto(
text = TextLine(
textRes = if (filteredCategories.isNotEmpty()) {
R.string.products_screen_welcome_header } else { null }
)
)
))
filteredCategories.toItems()?.let { addAll(it) }
}
productCategoriesLiveData.value?.embedded?.categories?.filter { categories ->
categories.isFeatured == false }.let { filteredCategories ->
if (filteredCategories != null) {
add(HeaderItem(ListSectionHeaderItemViewDto(
text = TextLine(
textRes = if (filteredCategories.isNotEmpty()) {
R.string.products_screen_welcome_header } else { null }
)
)
))
}
filteredCategories.toItems()?.let { addAll(it) }
}
}
}
private fun List<CategoriesItemModel>?.toItems(): List<ProductItem>? =
this?.mapIndexed { index, item ->
if (item.isFeatured == true) {
ProductItem.FeaturedProduct(
id = item.id as Any,
name = item.name,
dto = BigTileDto(
title = TextLine(text = item.name),
image = item.id.toString().let { toFeatureIcon(it, item.isFeatured) },
description = TextLine(item.description.toString()),
background = BackgroundType.SINGLE
)
)
} else {
ProductItem.NormalProduct(
id = item.id as Any,
name = item.name,
dto = ListButtonItemViewDto(
firstLine = TextLine(text = item.name),
rightDrawable = R.drawable.ic_arrow_right,
separatorDrawable = R.drawable.list_divider_margin_start_72dp,
background = index.indexToBackgroundType(this.size),
avatarDto = AvatarDto(iconBackgroundColor = R.color.ubs_concrete, avatarSize = AvatarDto.AvatarSize.SMALL_ICON_SIZE, iconId = toFeatureIcon(
item.id, item.isFeatured
)),
)
)
}
}
private fun toFeatureIcon(id: String?, isFeature: Boolean?): Int = if (ProductFeature.verify(id) == true) {
ProductFeature.icon()
} else { if (isFeature == true) { R.drawable.abc_vector_test } else {
R.drawable.balloon_illustration } }
}
This is my first time posting. I have made a simple counting app. I can connect and add data to the database, but i just cannot figure out how to view the data in the COLUMN_COUNT field. I have created a retrieveCount function, but cannot figure out how to call it on the HistoryAdapter page without making errors.
I have pasted the 4 files with code below.
MainActivity.kt
package com.example.thesupremecounter
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast
import java.text.SimpleDateFormat
import java.util.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val addButton = findViewById<LinearLayout>(R.id.addButton)
val reduceButton = findViewById<LinearLayout>(R.id.reduceButton)
val resetButton = findViewById<LinearLayout>(R.id.resetButton)
val myTextView = findViewById<TextView>(R.id.textView)
val saveButton = findViewById<Button>(R.id.saveButton)
val historyButton = findViewById<Button>(R.id.historyButton)
var timeClicked = 0
addButton.setOnClickListener {
timeClicked += 1
myTextView.text = timeClicked.toString()
// Toast.makeText(this#MainActivity, "You clicked me.", Toast.LENGTH_SHORT).show()
}
reduceButton.setOnClickListener {
timeClicked -= 1
if (timeClicked < 0) {
timeClicked = 0
} else {
myTextView.text = timeClicked.toString()
// Toast.makeText(this#MainActivity, "You clicked me.", Toast.LENGTH_SHORT).show()
}
}
resetButton.setOnClickListener {
timeClicked = 0
myTextView.text = timeClicked.toString()
// Toast.makeText(this#MainActivity, "You clicked me.", Toast.LENGTH_SHORT).show()
}
historyButton.setOnClickListener {
val intent = Intent(this, HistoryActivity::class.java)
startActivity(intent)
}
saveButton.setOnClickListener {
val count = timeClicked.toString()
val c = Calendar.getInstance() // Calender Current Instance
val dateTime = c.time // Current Date and Time of the system.
val sdf = SimpleDateFormat("dd MMM yyyy HH:mm:ss", Locale.getDefault()) // Date Formatter
val date = sdf.format(dateTime) // dateTime is formatted in the given format.
val dbHandler = SqliteOpenHelper(this, null)
dbHandler.addDate(count, date) // Add date function is called.
Toast.makeText(this#MainActivity, count + date, Toast.LENGTH_SHORT).show()
}
}
}
HistoryActivity.kt
package com.example.thesupremecounter
import android.os.Bundle
import android.view.View
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
class HistoryActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_history)
val toolbarPageTwo = findViewById<androidx.appcompat.widget.Toolbar>(R.id.toolbar_history_activity)
setSupportActionBar(toolbarPageTwo)
supportActionBar?.setDisplayHomeAsUpEnabled(true) //set back button
supportActionBar?.title = "HISTORY" // Setting an title in the action bar.
toolbarPageTwo.setNavigationOnClickListener {
onBackPressed()
}
getAllCompletedDates()
}
private fun getAllCompletedDates() {
val dbHandler = SqliteOpenHelper(this, null)
val allCompletedDatesList = dbHandler.getAllCompletedDatesList()
val tvHistory = findViewById<TextView>(R.id.tvHistory)
val rvHistory = findViewById<androidx.recyclerview.widget.RecyclerView>(R.id.rvHistory)
val tvNoDataAvailable = findViewById<TextView>(R.id.tvNoDataAvailable)
if (allCompletedDatesList.size > 0) {
tvHistory.visibility = View.VISIBLE
rvHistory.visibility = View.VISIBLE
tvNoDataAvailable.visibility = View.GONE
rvHistory.layoutManager = LinearLayoutManager(this)
val historyAdapter = HistoryAdapter(this, allCompletedDatesList)
rvHistory.adapter = historyAdapter
} else {
tvHistory.visibility = View.GONE
rvHistory.visibility = View.GONE
tvNoDataAvailable.visibility = View.VISIBLE
}
}
}
SqliteOpenHelper.kt
package com.example.thesupremecounter
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
class SqliteOpenHelper(
context: Context,
factory: SQLiteDatabase.CursorFactory?
) :
SQLiteOpenHelper(
context, DATABASE_NAME,
factory, DATABASE_VERSION
) {
override fun onCreate(db: SQLiteDatabase) {
val CREATE_HISTORY_TABLE = ("CREATE TABLE " + TABLE_HISTORY +
"(" + COLUMN_ID + " INTEGER PRIMARY KEY,"
+ COLUMN_COUNT + " TEXT,"
+ COLUMN_COMPLETED_DATE + " TEXT" + ")")
db.execSQL(CREATE_HISTORY_TABLE)
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_HISTORY) // It drops the existing history table
onCreate(db) // Calls the onCreate function so all the updated table will be created.
}
fun addDate(count: String, date: String ) {
val values = "INSERT INTO history " +
"( 'count', 'completed_date')" +
" VALUES " +
"( '$count', '$date')"
val db = this.writableDatabase
db.execSQL(values)
db.close()
}
fun retrieveCount(): ArrayList<String> {
val countList = ArrayList<String>() // ArrayList is initialized
val db = this.readableDatabase
val cursor = db.rawQuery("SELECT * FROM $TABLE_HISTORY", null)
while (cursor.moveToNext())
{countList.add(cursor.getString(cursor.getColumnIndex(COLUMN_COUNT)))
}
cursor.close()
return countList
}
fun getAllCompletedDatesList(): ArrayList<String> {
val list = ArrayList<String>() // ArrayList is initialized
val db = this.readableDatabase
val cursor = db.rawQuery("SELECT * FROM $TABLE_HISTORY", null)
while (cursor.moveToNext())
{list.add(cursor.getString(cursor.getColumnIndex(COLUMN_COMPLETED_DATE)))
}
cursor.close()
return list
}
companion object {
const val DATABASE_VERSION = 1 // This DATABASE Version
const val DATABASE_NAME = "TheCountDatabase9.db" // Name of the DATABASE
const val TABLE_HISTORY = "history" // Table Name
const val COLUMN_ID = "_id" // Column Id
const val COLUMN_COUNT = "count" // Count
const val COLUMN_COMPLETED_DATE = "completed_date" // Column for Completed Date
}
}
HistoryAdapter.kt
package com.example.thesupremecounter
import android.content.Context
import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.item_history_row.view.*
class HistoryAdapter(val context: Context, val items: ArrayList<String>) :
RecyclerView.Adapter<HistoryAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
LayoutInflater.from(context).inflate(
R.layout.item_history_row,
parent,
false
)
)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val date: String = items[position]
holder.tvPosition.text = (position + 1).toString()
holder.tvCount.text = "unsure what code to write here to display count values from COLUMN_COUNT + also not sure how to call the retrieve count function"
holder.tvItem.text = date
if (position % 2 == 0) {
holder.llHistoryItemMain.setBackgroundColor(
Color.parseColor("#EBEBEB")
)
} else {
holder.llHistoryItemMain.setBackgroundColor(
Color.parseColor("#FFFFFF")
)
}
}
override fun getItemCount(): Int {
return items.size
}
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val llHistoryItemMain = view.ll_history_item_main!!
val tvItem = view.tvItem!!
val tvPosition = view.tvPosition!!
val tvCount = view.tvCount!!
}
}
Any help will be greatly appreciated.
Thanks
A recyclerview is designed to display the contents of the list that is passed to it (items in your case).
so :-
holder.tvCount.text = "unsure what code to write here to display count values from COLUMN_COUNT + also not sure how to call the retrieve count function"
Should be the count in items, however items is just the date. You need items to be a little more complex i.e. a list of more than just the one String.
So create a class such as HistoryRow with members for each of the components e.g.
data class HistoryRow(
val id: String,
val count: String,
val date: String
)
in the working example below I just added this as a sub class of SqliteOpenHelper
The instead create a List in your getAllCompletedDatesList() you create a List and pass this to your Adapter.
Then in the onBindViewHolder method/function you then assign the values from the respective elements.
The following is a working example based upon the above.
First SqliteOpenHelper :-
class SqliteOpenHelper(
context: Context,
factory: SQLiteDatabase.CursorFactory?
) :
SQLiteOpenHelper(
context, DATABASE_NAME,
factory, DATABASE_VERSION
) {
override fun onCreate(db: SQLiteDatabase) {
val CREATE_HISTORY_TABLE = ("CREATE TABLE " + TABLE_HISTORY +
"(" + COLUMN_ID + " INTEGER PRIMARY KEY,"
+ COLUMN_COUNT + " TEXT,"
+ COLUMN_COMPLETED_DATE + " TEXT" + ")")
db.execSQL(CREATE_HISTORY_TABLE)
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_HISTORY) // It drops the existing history table
onCreate(db) // Calls the onCreate function so all the updated table will be created.
}
fun addDate(count: String, date: String ) {
val values = "INSERT INTO history " +
"( 'count', 'completed_date')" +
" VALUES " +
"( '$count', '$date')"
val db = this.writableDatabase
db.execSQL(values)
db.close()
}
fun retrieveCount(): ArrayList<String> {
val countList = ArrayList<String>() // ArrayList is initialized
val db = this.readableDatabase
val cursor = db.rawQuery("SELECT * FROM $TABLE_HISTORY", null)
while (cursor.moveToNext())
{countList.add(cursor.getString(cursor.getColumnIndex(COLUMN_COUNT)))
}
cursor.close()
return countList
}
fun getAllCompletedDatesList(): ArrayList<HistoryRow> {
val list = ArrayList<HistoryRow>() // ArrayList is initialized
val db = this.readableDatabase
val cursor = db.rawQuery("SELECT * FROM $TABLE_HISTORY", null)
while (cursor.moveToNext())
list.add(
HistoryRow(
cursor.getString(cursor.getColumnIndex(COLUMN_ID)),
cursor.getString(cursor.getColumnIndex(COLUMN_COUNT)),
cursor.getString(cursor.getColumnIndex(COLUMN_COMPLETED_DATE))
)
)
cursor.close()
return list
}
companion object {
const val DATABASE_VERSION = 1 // This DATABASE Version
const val DATABASE_NAME = "TheCountDatabase9.db" // Name of the DATABASE
const val TABLE_HISTORY = "history" // Table Name
const val COLUMN_ID = "_id" // Column Id
const val COLUMN_COUNT = "count" // Count
const val COLUMN_COMPLETED_DATE = "completed_date" // Column for Completed Date
}
data class HistoryRow(
val id: String,
val count: String,
val date: String
)
}
HistoryRow class added (could be elsewhere but added here for brevity)
Note the changes to the getAllCompletedDatesList() method/function to build and return an ArrayList<HistoryRow> instead of the ArrayList<String>.
The other changes required are for the HistoryAdapter which was changed to :-
class HistoryAdapter(val context: Context, val items: ArrayList<SqliteOpenHelper.HistoryRow>) :
RecyclerView.Adapter<HistoryAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
LayoutInflater.from(context).inflate(
R.layout.item_history_row,
parent,
false
)
)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.tvPosition.setText((position + 1).toString())
holder.tvCount.setText(items[position].count)
holder.tvItem.setText(items[position].date)
if (position % 2 == 0) {
holder.llHistoryItemMain.setBackgroundColor(
Color.parseColor("#EBEBEB")
)
} else {
holder.llHistoryItemMain.setBackgroundColor(
Color.parseColor("#FFFFFF")
)
}
}
override fun getItemCount(): Int {
return items.size
}
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val llHistoryItemMain = view.findViewById<LinearLayout>(R.id.ll_history_item_main)
val tvItem = view.findViewById<TextView>(R.id.tvItem)
val tvPosition = view.findViewById<TextView>(R.id.tvPosition)
val tvCount = view.findViewById<TextView>(R.id.tvCount)
}
}
items changed from ArrayList to ArrayList
onBindViewHolder assigns values from the elements of items
I'm not sure why I had to change the ViewHolder to use view.FindViewById but I had to.
As I had to create the layouts I have commented out setting the toolbar so as not to have to go to the pains of creating appropriate layouts. Obviously the layouts may differ. However when run the following results were achieved:-
When first run :-
When History is clicked (no data as yet, as expected) :-
Going back to Main and clicking SAVE 3 times and then to History :-
i.e. the 3 rows are now displayed with the respective data (albeit the same data)
my app working fine any without problem , i used AsyncTask to get data json and every thing is fine . i want to add code to check internet connection in my app and i put code under onCreate in main activity .
val cm = baseContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkInfo = cm.activeNetworkInfo
if (networkInfo != null && networkInfo.isConnected){
if (networkInfo.type == ConnectivityManager.TYPE_WIFI){
Toast.makeText(baseContext,"wifi",Toast.LENGTH_SHORT).show()
}
if (networkInfo.type == ConnectivityManager.TYPE_MOBILE){
Toast.makeText(baseContext,"MOBILE",Toast.LENGTH_SHORT).show()
}
}else {
Toast.makeText(baseContext,"MOBILE",Toast.LENGTH_SHORT).show()
this.finish()
}
when l put the phone on airplan mode and launching app he is stop working . and crash .
console log
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: com.iraqairoirt.iraqairports, PID: 10868
main activity
package com.iraqairoirt.iraqairports
import android.annotation.SuppressLint
import android.content.Context
import android.content.DialogInterface
import android.os.AsyncTask
import android.os.Bundle
import android.support.design.widget.NavigationView
import android.support.v4.view.GravityCompat
import android.support.v7.app.ActionBarDrawerToggle
import android.support.v7.app.AlertDialog
import android.support.v7.app.AppCompatActivity
import android.view.Menu
import android.view.MenuItem
import android.widget.TextView
import com.iraqairoirt.iraqairports.BaghdadAirport.ListAdapteArr
import com.iraqairoirt.iraqairports.BaghdadAirport.ListAdapteDep
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.content_main.*
import kotlinx.android.synthetic.main.fragment_baghdada_arrivel.*
import kotlinx.android.synthetic.main.fragment_baghdada_dep.*
import org.json.JSONArray
import org.json.JSONObject
import java.net.HttpURLConnection
import java.net.URL
import android.widget.Toast
import android.content.Intent
import android.content.IntentFilter
import android.net.ConnectivityManager
import android.net.NetworkInfo
import android.support.design.widget.Snackbar
import com.iraqairoirt.iraqairports.BaghdadAirport.FlightsArrivelBeforBGW
import com.iraqairoirt.iraqairports.BaghdadAirport.FlightsDepBeforBGW
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val url = "airport.json"
Arr().execute(url)
setSupportActionBar(toolbar)
val fragmentAdapter = MyPagerAdapter(supportFragmentManager)
viewpager_main.adapter = fragmentAdapter
sliding_tabs.setupWithViewPager(viewpager_main)
val toggle = ActionBarDrawerToggle(
this, drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close
)
drawer_layout.addDrawerListener(toggle)
toggle.syncState()
nav_view.setNavigationItemSelectedListener(this)
val cm = baseContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkInfo = cm.activeNetworkInfo
if (networkInfo != null && networkInfo.isConnected){
if (networkInfo.type == ConnectivityManager.TYPE_WIFI){
Toast.makeText(baseContext,"wifi",Toast.LENGTH_SHORT).show()
}
if (networkInfo.type == ConnectivityManager.TYPE_MOBILE){
Toast.makeText(baseContext,"MOBILE",Toast.LENGTH_SHORT).show()
}
}else {
Toast.makeText(baseContext,"MOBILE",Toast.LENGTH_SHORT).show()
this.finish()
}
}
// full class for json api
inner class Arr : AsyncTask<String, String, String>() {
val progressDialog = AlertDialog.Builder(this#MainActivity)
val dialogView = layoutInflater.inflate(R.layout.progress_dialog, null)
val message = dialogView.findViewById<TextView>(R.id.message_id)
val dialog = progressDialog.create()
override fun onPreExecute() {
super.onPreExecute()
dialog.setMessage("يرجى الانتظار")
dialog.setCancelable(false)
dialog.show()
}
// for build connection
override fun doInBackground(vararg url: String?): String {
var text: String
val connection = URL(url[0]).openConnection() as HttpURLConnection
try {
connection.connect()
text = connection.inputStream.use { it.reader().use { reader -> reader.readText() } }
} finally {
connection.disconnect()
}
return text
}
override fun onPostExecute(result: String?) {
super.onPostExecute(result)
handleJson(result)
dialog.dismiss();
}
override fun onProgressUpdate(vararg text: String?) {
}
#SuppressLint("WrongViewCast")
private fun handleJson(jsonString: String?) {
val jsonObj = JSONObject(jsonString)
val result = jsonObj.getJSONObject("result")
val response = result.getJSONObject("response")
val airport = response.getJSONObject("airport")
val pluginData = airport.getJSONObject("pluginData")
val schedule = pluginData.getJSONObject("schedule")
val arrivals = schedule.getJSONObject("arrivals")
// weather data
val weather = pluginData.getJSONObject("weather")
val mater = weather.getString("metar")
// MaterText.text=mater
// val data = arrivals.getJSONObject("data")
val jsonArray = JSONArray(arrivals.get("data").toString())
val list = ArrayList<FlightShdu>()
var x = 0
while (x < jsonArray.length()) {
val jsonObject = jsonArray.getJSONObject(x)
list.add(
FlightShdu(
jsonObject.getJSONObject("flight").getJSONObject("identification").getJSONObject("number").getString(
"default"
),
jsonObject.getJSONObject("flight").getJSONObject("airline").getString("short"),
jsonObject.getJSONObject("flight").getJSONObject("status").getJSONObject("generic").getJSONObject(
"status"
).getString("text"),
jsonObject.getJSONObject("flight").getJSONObject("airline").getJSONObject("code").getString("icao"),
jsonObject.getJSONObject("flight").getJSONObject("time").getJSONObject("scheduled").getString("arrival"),
jsonObject.getJSONObject("flight").getJSONObject("airport").getJSONObject("origin").getJSONObject(
"code"
).getString("iata"),
jsonObject.getJSONObject("flight").getJSONObject("aircraft").getJSONObject("model").getString("code"),
// for more information
jsonObject.getJSONObject("flight").getJSONObject("time").getJSONObject("real").getString("departure"),
jsonObject.getJSONObject("flight").getJSONObject("time").getJSONObject("estimated").getString("arrival"),
// jsonObject.getJSONObject("flight").getJSONObject("time").getJSONObject("estimated").getString("arrival"),
jsonObject.getJSONObject("flight").getJSONObject("aircraft").getString("registration"),
jsonObject.getJSONObject("flight").getJSONObject("status").getJSONObject("generic").getJSONObject(
"status"
).getString("diverted"),
arrivals.getString("timestamp"),
jsonObject.getJSONObject("flight").getJSONObject("status").getString("icon")
)
)
x++
}
list.forEach(::println)
var adapter = ListAdapteArr(this#MainActivity, list)
flight_arrivel_list.adapter = adapter
}
}
override fun onBackPressed() {
if (drawer_layout.isDrawerOpen(GravityCompat.START)) {
drawer_layout.closeDrawer(GravityCompat.START)
} else {
super.onBackPressed()
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.main, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val id = item.itemId
//noinspection SimplifiableIfStatement
if (id == R.id.flightarrbeforbgw) {
val intent = Intent(this, FlightsArrivelBeforBGW::class.java)
this.startActivity(intent)
return true
}
if (id == R.id.flightdepbefrobgw) {
val intent = Intent(this, FlightsDepBeforBGW::class.java)
this.startActivity(intent)
return true
}
//
// if (id == R.id.searchflights) {
// Toast.makeText(this, "Android Menu is Clicked", Toast.LENGTH_LONG).show()
// return true
// }
return super.onOptionsItemSelected(item)
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
// Handle navigation view item clicks here.
when (item.itemId) {
R.id.nav_camera -> {
// Handle the camera action
}
R.id.nav_gallery -> {
}
R.id.nav_slideshow -> {
}
R.id.nav_manage -> {
}
R.id.nav_share -> {
}
R.id.nav_send -> {
}
}
drawer_layout.closeDrawer(GravityCompat.START)
return true
}
}
to avoid fatal error and crash when there is not internet connection ,my mistake is i should put execute() url inside code of check internet connection
val cm = baseContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkInfo = cm.activeNetworkInfo
if (networkInfo != null && networkInfo.isConnected){
if (networkInfo.type == ConnectivityManager.TYPE_WIFI){
val url = "airport.json"
Arr().execute(url)
}
if (networkInfo.type == ConnectivityManager.TYPE_MOBILE){
val url = "airport.json"
Arr().execute(url)
}
}else {
val builder = AlertDialog.Builder(this)
builder.setTitle("No internet Connection")
builder.setMessage("Please turn on internet connection to continue")
builder.setNegativeButton(
"close"
) { dialog, button -> this.finish() }
val alertDialog = builder.create()
alertDialog.show()
}
now my app working fine =)
I want game to be set to a new instance of Game and I want to pass this into game. SO this is what I have.
var game: Game
init {
game = Game(this)
}
I have also tried
var game: Game = Game(this)
both threw a NullPointer at run time but it seems fine in Intellij and has no problem compiling. What am I doing wrong?
Stack Trace
org.bukkit.plugin.InvalidPluginException: java.lang.NullPointerException
at org.bukkit.plugin.java.JavaPluginLoader.loadPlugin(JavaPluginLoader.java:135) ~[server.jar:git-Spigot-21fe707-e1ebe52]
at org.bukkit.plugin.SimplePluginManager.loadPlugin(SimplePluginManager.java:329) ~[server.jar:git-Spigot-21fe707-e1ebe52]
at org.bukkit.plugin.SimplePluginManager.loadPlugins(SimplePluginManager.java:251) [server.jar:git-Spigot-21fe707-e1ebe52]
at org.bukkit.craftbukkit.v1_8_R3.CraftServer.loadPlugins(CraftServer.java:292) [server.jar:git-Spigot-21fe707-e1ebe52]
at net.minecraft.server.v1_8_R3.DedicatedServer.init(DedicatedServer.java:198) [server.jar:git-Spigot-21fe707-e1ebe52]
at net.minecraft.server.v1_8_R3.MinecraftServer.run(MinecraftServer.java:525) [server.jar:git-Spigot-21fe707-e1ebe52]
at java.lang.Thread.run(Thread.java:745) [?:1.8.0_121]
Caused by: java.lang.NullPointerException
at org.bukkit.plugin.SimplePluginManager.registerEvents(SimplePluginManager.java:523) ~[server.jar:git-Spigot-21fe707-e1ebe52]
at me.darkpaladin.uhc.game.gameSettings.GameSettingsManager.addGameSettings(GameSettingsManager.kt:43) ~[?:?]
at me.darkpaladin.uhc.game.gameSettings.GameSettingsManager.<init>(GameSettingsManager.kt:20) ~[?:?]
at me.darkpaladin.uhc.game.Game.<init>(Game.kt:49) ~[?:?]
at me.darkpaladin.uhc.UHC.<init>(UHC.kt:20) ~[?:?]
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:1.8.0_121]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[?:1.8.0_121]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[?:1.8.0_121]
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[?:1.8.0_121]
at java.lang.Class.newInstance(Class.java:442) ~[?:1.8.0_121]
at org.bukkit.plugin.java.PluginClassLoader.<init>(PluginClassLoader.java:76) ~[server.jar:git-Spigot-21fe707-e1ebe52]
at org.bukkit.plugin.java.JavaPluginLoader.loadPlugin(JavaPluginLoader.java:131) ~[server.jar:git-Spigot-21fe707-e1ebe52]
... 6 more
UHC Class
var game: Game
init {
game = Game(this)
}
override fun onReady() {
// new Lobby(Bukkit.getWorld("world"), this, false);
TeamManager()
registerCommands()
}
fun registerCommands() {
val c = commandHandler
c.addCommand(
TeamCommand(),
SetGameTypeCommand(game),
ClaimHostCommand(game),
StartGameCommand(game),
ScenarioManagerCommand(game),
KillTopCommand(game),
ConfigCommand(game),
ScatterCommand(game)
)
}
fun registerListeners() {
val p = Bukkit.getPluginManager()
p.registerEvents(GamePlayerListener(game), this)
}
Game Class
package me.darkpaladin.uhc.game
import me.darkpaladin.core.Core
import me.darkpaladin.core.utils.CoreUtils
import me.darkpaladin.core.utils.PacketUtils
import me.darkpaladin.uhc.UHC
import me.darkpaladin.uhc.events.GameStartEvent
import me.darkpaladin.uhc.events.GameStopEvent
import me.darkpaladin.uhc.game.gameEvents.GameEvent
import me.darkpaladin.uhc.game.gameEvents.GameEventRunnable
import me.darkpaladin.uhc.game.gamePlayers.GamePlayer
import me.darkpaladin.uhc.game.gamePlayers.GamePlayerManager
import me.darkpaladin.uhc.game.gameSettings.GameSettingsManager
import me.darkpaladin.uhc.scenarios.ScenarioManager
import org.apache.commons.lang.WordUtils
import org.bukkit.*
import org.bukkit.entity.Item
import org.bukkit.entity.Monster
import org.bukkit.entity.Player
import org.bukkit.scheduler.BukkitRunnable
import java.util.*
/**
* Created by Caleb on 4/28/2017.
*/
class Game(private val plugin: UHC) {
var gameType = GameType.NORMAL
var gameState = GameState.SETTING_UP
var gameStartTicks = (CoreUtils.ticksPerSecond * 10).toLong()
var finalHealTime = (CoreUtils.ticksPerSecond * 15).toLong()
var pvpTicks = (CoreUtils.ticksPerSecond * 20).toLong()
var meetupTicks = (CoreUtils.ticksPerSecond * 25).toLong()
var isBorderShrink = true
var episodeLength = (CoreUtils.ticksPerMinute * 20).toLong()
private var episode = 1
private val worlds = ArrayList<World>()
private val gameEvents = ArrayList<GameEvent>()
var gameTicks: Long = 0L
var hostUuid: UUID? = null
val scenarioManager: ScenarioManager = ScenarioManager(this)
val gamePlayerManager: GamePlayerManager = GamePlayerManager()
val gameSettingsManager: GameSettingsManager = GameSettingsManager(this)
private val instance: Game
init {
worlds.add(Bukkit.getWorld("world")) //TODO: remove
instance = this
}
val overworld: World?
get() = getWorldWithEnvironment(World.Environment.NORMAL)
val nether: World?
get() = getWorldWithEnvironment(World.Environment.NETHER)
val end: World?
get() = getWorldWithEnvironment(World.Environment.THE_END)
fun getWorldWithEnvironment(environment: World.Environment): World? {
return worlds.firstOrNull { it.environment == environment }
}
fun addGameEvent(vararg events: GameEvent) {
gameEvents.addAll(Arrays.asList(*events))
}
val host: Player
get() = Bukkit.getPlayer(hostUuid)
fun start() {
gameState = GameState.STARTING
val finalHeal = GameEvent("Final Heal", finalHealTime, object : GameEventRunnable(this) {
override fun run() {
Bukkit.getOnlinePlayers().forEach { player -> player.health = player.maxHealth }
CoreUtils.broadcast(Core.PREFIX + "Final Heal has been given. This is the FINAL heal. Do not ask for more.")
}
})
val pvp = GameEvent("PvP", pvpTicks, object : GameEventRunnable(this) {
override fun run() {
for (world in worlds) {
world.pvp = true
world.setGameRuleValue("doMobSpawning", "true")
}
}
})
val starting = GameEvent("Starting in", gameStartTicks, object : GameEventRunnable(this) {
override fun run() {
gameTicks = 0L
addGameEvent(finalHeal, pvp)
if (isBorderShrink)
addGameEvent(BorderShrinkGameEvent(meetupTicks, instance))
for (player in Bukkit.getOnlinePlayers()) {
player.health = player.maxHealth
player.foodLevel = 20
player.saturation = 20f
player.level = 0
player.exp = 0f
player.totalExperience = 0
player.closeInventory()
player.inventory.clear()
player.inventory.armorContents = null
player.gameMode = GameMode.SURVIVAL
player.activePotionEffects.forEach { potionEffect -> player.removePotionEffect(potionEffect.type) }
}
for (world in worlds) {
for (entity in world.entities) {
if (entity is Item || entity is Monster) {
entity.remove()
}
}
world.pvp = false
world.difficulty = Difficulty.HARD
world.time = 20
world.setSpawnFlags(false, false)
}
Bukkit.getOnlinePlayers().forEach { player -> gamePlayerManager.addGamePlayers(GamePlayer(player.uniqueId)) }
val players = ArrayList<Player>()
gamePlayerManager.aliveGamePlayers
.filter { gamePlayer -> gamePlayer.player != null }
.forEach { gamePlayer -> players.add(gamePlayer.player) }
scenarioManager.giveStartingItems(players)
gameState = GameState.RUNNING
Bukkit.getPluginManager().callEvent(GameStartEvent(instance))
}
})
addGameEvent(starting)
GameTimer().runTaskTimer(plugin, 0, 1)
if (gameType === GameType.RECORDED)
EpisodeTimerTask()
}
val nextEvent: GameEvent?
get() {
val events = gameEvents
val times = HashMap<GameEvent, Long>()
events.forEach { gameEvent -> times.put(gameEvent, gameEvent.time) }
var nextEvent: GameEvent? = null
var nextEventTime: Long = 999999999999999999L
for (event in times.keys) {
if (event.time < nextEventTime) {
nextEvent = event
nextEventTime = event.time
}
}
return nextEvent
}
fun getNextBorderRadius(world: World): Int {
return Math.round(world.worldBorder.size / 2 * .75).toInt()
}
private inner class GameTimer : BukkitRunnable() {
override fun run() {
val nextEvent = nextEvent
if (nextEvent != null) {
if (gameTicks!! % 20 == 0L) {
PacketUtils.sendAction(Core.HIGHLIGHTED_COLOR.toString() + ChatColor.BOLD.toString() + WordUtils.capitalizeFully(nextEvent.name) + Core.EXTRA_COLOR + " » " + Core.HIGHLIGHTED_COLOR + CoreUtils.formatTicks(nextEvent.time - gameTicks!!))
}
if (gameTicks >= nextEvent.time) {
nextEvent.runnable!!.run()
gameEvents.remove(nextEvent)
}
}
gameTicks++
}
}
private inner class BorderShrinkGameEvent(time: Long, game: Game) : GameEvent("Border Shrink", time, object : GameEventRunnable(game) {
override fun run() {
for (world in worlds) {
val wb = world.worldBorder
val radius = Math.round(wb.size / 2).toInt()
val newRadius = Math.round(wb.size / 2 * .75).toInt()
if (newRadius < 50)
wb.size = 100.0
else
wb.size = (newRadius * 2).toDouble()
CoreUtils.broadcast(Core.PREFIX + "The border has shrunk from " + radius + " to " + Math.round(wb.size / 2).toInt() + "!")
if (wb.size > 100) {
game.addGameEvent(BorderShrinkGameEvent(CoreUtils.ticksPerSecond * 5 + game.gameTicks!!, game))
}
}
}
})
private inner class EpisodeTimerTask : BukkitRunnable() {
private var ticks: Long = 0
init {
ticks = episodeLength
}
override fun run() {
if (ticks <= 0) {
cancel()
CoreUtils.broadcast(Core.PREFIX + "End of episode " + episode + ". Start episode " + episode + 1)
episode++
return
}
ticks--
}
}
fun stop() {
scenarioManager.disableAll()
Bukkit.getPluginManager().callEvent(GameStopEvent(this))
plugin.game = Game(plugin)
}
}
Game Setting Manager
package me.darkpaladin.uhc.game.gameSettings
import me.darkpaladin.core.Core
import me.darkpaladin.uhc.game.Game
import org.bukkit.Bukkit
import org.bukkit.event.Listener
import java.util.ArrayList
import java.util.Arrays
import java.util.stream.Collectors
/**
* Created by caleb on 5/6/17.
*/
class GameSettingsManager(game: Game) {
private val gameSettings = ArrayList<GameSetting>()
init {
addGameSettings(
FriendlyFireGameSetting(game),
NotchApplesGameSetting(),
DoubleArrowsGameSetting()
)
}
fun getGameSettings(): List<GameSetting> {
return gameSettings
}
val toggleableGameSettings: List<ToggleableGameSetting>
get() {
val settings = ArrayList<ToggleableGameSetting>()
for (setting in getGameSettings())
if (setting is ToggleableGameSetting)
settings.add(setting)
return settings
}
fun addGameSettings(vararg gameSettings: GameSetting) {
this.gameSettings.addAll(Arrays.asList(*gameSettings))
for(setting in gameSettings)
Bukkit.getPluginManager().registerEvents(setting as Listener, Core.instance)
}
fun getGameSetting(name: String): GameSetting {
return gameSettings.stream()
.filter { gameSetting -> gameSetting.name.equals(name, ignoreCase = true) }
.collect(Collectors.toList<GameSetting>())[0]
}
}
On line 43 of the GameSettingsManager:
fun addGameSettings(vararg gameSettings: GameSetting) {
this.gameSettings.addAll(Arrays.asList(*gameSettings))
for(setting in gameSettings) //line 43 is the one below this
Bukkit.getPluginManager().registerEvents(setting as Listener, Core.instance)
}
One of your setting objects that is being passed into Bukkit.getPluginManager() is null.
Or Core.Instance is null.
One other possibility is that the object being returned by getPluginManager() has an unitialized variable inside it that is being referenced in the registerEvents() function.
But the most likely case is that one of your setting objects is null or Core.Instance is null.
Edit
https://github.com/Bukkit/Bukkit/blob/master/src/main/java/org/bukkit/plugin/SimplePluginManager.java
Here is the registerEvents() function from the SimplePluginManager in the bukkit library that gets run:
public void registerEvents(Listener listener, Plugin plugin) {
if (!plugin.isEnabled()) {
//the next line is 523
throw new IllegalPluginAccessException("Plugin attempted to register " + listener + " while not enabled");
}
for (Map.Entry<Class<? extends Event>, Set<RegisteredListener>> entry : plugin.getPluginLoader().createRegisteredListeners(listener, plugin).entrySet()) {
getEventListeners(getRegistrationClass(entry.getKey())).registerAll(entry.getValue());
}
}
According to your stack trace line 523 is the one throwing the null pointer exception. So something there is null. The listener variable is coming from your gameSettings array though.
Looking at your code there really shouldn't be a null in that gameSettings varargs array. But the function that throws the error is saying otherwise. It would be a good idea to debug to that location or do a println as your looping through the gameSettings array to verify that none of it is null.