在保存之前初始化空对象并在活动之间传递
Posted
技术标签:
【中文标题】在保存之前初始化空对象并在活动之间传递【英文标题】:Initializing null object and pass between activities before saving 【发布时间】:2021-07-02 22:08:23 【问题描述】:我正在尝试做一些对我来说非常复杂的事情....我正在尝试创建包含两个对象的发票 1) Invoice 2) InvoiceItems(行项目)
相同的活动用于编辑现有发票或创建新发票,因此 Invoice 和 InvoiceItems 都可以为空。
我试图让这项工作的方式是在活动启动时,
-
用户在表单中输入发票活动的详细信息
用户点击添加项目详细信息(输入标题等数据的发票,在点击时将 invoiceItems 发送到编辑 InvoiceItems 活动)
启动新活动以添加单个项目详细信息
进行了更改并更新了发票项目
按返回时,对象将再次发送回上一个活动
问题有两个方面:
-
这是正确的方法吗?
在发送到 InvoiceItem 活动之前将字段详细信息添加到发票对象时出现空点错误异常
请看下面的代码:
class EditInvoice : AppCompatActivity()
companion object
@JvmStatic
fun start(context: Context, invoice: Invoice?, invoiceItems: InvoiceItems?)
val starter = Intent(context, EditInvoice::class.java)
.putExtra("invoice", invoice)
.putExtra("invoiceItems", invoiceItems)
context.startActivity(starter)
private var invoice: Invoice? = null
private var invoiceEdit: Invoice? = null
private lateinit var contact: Contact
private var invoiceItems: List<InvoiceItems>? = null
private lateinit var dueDate: Calendar
private val calendar = Calendar.getInstance()
private var total = 0
private var subTotal = 0
private var taxrate = 0
private var invoiceType: String = ""
private var invoiceUpdt: InvoiceItems? = null
private var j: Int = 0
private var clientLkey: String? = ""
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_edit_invoice)
val toolbar: Toolbar = findViewById(R.id.toolbar_editinv)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayShowHomeEnabled(true)
val invoiceClient = findViewById<AutoCompleteTextView>(R.id.invoiceClient)
val invoiceDueDt = findViewById<TextView>(R.id.invoiceDueDt)
dueDate = Calendar.getInstance()
//getting values from intent
invoice = intent.getSerializableExtra("invoice") as? Invoice
invoiceItems = intent.getSerializableExtra("invoiceItem") as? List<InvoiceItems>
invoiceUpdt = intent.getSerializableExtra("invoiceItemUpdt") as? InvoiceItems
j = intent.getIntExtra("i",0)
if (invoice == null)
invoiceType = "new"
edit_inv.text = "Add Invoice"
invoiceEdit = Invoice("0","0","0","0","0","0",0,0,null,"")
addinvoiceItem()
else
invoiceEdit = invoice
editInvoice()
//Setup Due date for the invoice
invoiceDueDt.setOnClickListener
showCalendar()
//Auto complete based on database for selecting the client
val clientContact: List<Contact> = ArrayList<Contact>()
val adapter = ClientSelectAdapter(this, R.layout.userlatomcontacts, clientContact)
invoiceClient.setAdapter(adapter)
invoiceClient.threshold = 2
invoiceClient.setOnItemClickListener parent, _, position, id ->
val selectedClient = parent.adapter.getItem(position) as Contact?
invoiceClient.setText(selectedClient?.name)
clientLkey = selectedClient?.lookupKey
val saveInvoice = findViewById<TextView>(R.id.editinv_save)
val invoiceTitle = findViewById<EditText>(R.id.invoiceTitle)
saveInvoice.setOnClickListener
if(invoiceTitle.toString().isEmpty())
Toast.makeText(this, "Invoice title can't be empty", Toast.LENGTH_SHORT).show()
return@setOnClickListener
if(invoiceClient.toString().isEmpty())
Toast.makeText(this, "Please select a Client for the invoice", Toast.LENGTH_SHORT).show()
return@setOnClickListener
if(invoiceDueDt.toString().isEmpty())
Toast.makeText(
this,
"Please enter the due date for the invoice",
Toast.LENGTH_SHORT
).show()
return@setOnClickListener
if(invoiceItems == null)
Toast.makeText(
this,
"Please enter the line items/services for the invoice",
Toast.LENGTH_SHORT
).show()
return@setOnClickListener
//updating values as current
updateInvoiceValues()
//Storing values to DB
val db = AppDatabase.getDatabase(this)
if(invoiceType == "new")
db.InvoicesDao().addInvoice(invoice!!)
for(i in invoiceItems!!.indices)
db.InvoiceItemsDao().addInvItem(invoiceItems!![i])
else
db.InvoicesDao().updateInvoice(invoice!!)
for(i in invoiceItems!!.indices)
db.InvoiceItemsDao().updateInvItem(invoiceItems!![i])
inner class ClientSelectAdapter(
context: Context,
@LayoutRes private val layoutResource: Int,
private var allContacts: List<Contact>
):
ArrayAdapter<Contact>(context, layoutResource, allContacts),
Filterable private var mContact: List<Contact> = allContacts
override fun getCount(): Int
return mContact.size
override fun getItem(p0: Int): Contact
return mContact[p0]
override fun getItemId(p0: Int): Long
// Or just return p0
return mContact[p0].id.toLong()
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View
var view = convertView
if (view == null)
view = LayoutInflater.from(parent.context)
.inflate(layoutResource, parent, false)
val invoiceClient = view!!.findViewById<View>(R.id.invClientName) as TextView
invoiceClient.text = mContact[position].name
val clientProfile = view.findViewById<View>(R.id.profile_image) as ShapeableImageView
Picasso.get().load(mContact[position].photoUri)
.placeholder(R.drawable.ic_baseline_whatshot_24).fit().centerCrop()
.into(clientProfile)
val contLabel = view.findViewById<View>(R.id.salesLabelText) as TextView
if(mContact[position].label != null)
contLabel.text = mContact[position].label
if (mContact[position].label == "Lead" || mContact[position].label == "LEAD")
contLabel.setBackgroundColor(resources.getColor(R.color.ColorPurple))
else if (mContact[position].label == "Qualified")
contLabel.setBackgroundColor(resources.getColor(R.color.ColorBlueNote))
else if (mContact[position].label== "Proposal")
contLabel.setBackgroundColor(resources.getColor(R.color.ColorMaroon))
else if (mContact[position].label == "Client")
contLabel.setBackgroundColor(resources.getColor(R.color.ColorGreen))
else if (mContact[position].label == "Invoiced")
contLabel.setBackgroundColor(resources.getColor(R.color.ColorYellow))
else if (mContact[position].label == "Unpaid")
contLabel.setBackgroundColor(resources.getColor(R.color.ColorRed))
else if (mContact[position].label == "")
salesLabel.visibility = View.GONE
return view
override fun getFilter(): Filter
return object : Filter()
override fun publishResults(
charSequence: CharSequence?,
filterResults: FilterResults
)
mContact = filterResults.values as List<Contact>
notifyDataSetChanged()
override fun performFiltering(charSequence: CharSequence?): FilterResults
var queryString = charSequence?.toString()?.toLowerCase(Locale.ROOT)
val results = FilterResults()
results.values = if (queryString == null || queryString.isEmpty())
allContacts
else
queryString = "%$charSequence%"
val db = AppDatabase.getDatabase(context)
allContacts = db.contactsDao().getBySearch(queryString)
allContacts
return results
private fun showCalendar()
val datePicker = DatePickerDialog(
this,
R.style.DateTimePickerTheme,
datePicker: DatePicker, year: Int, month: Int, day: Int ->
dueDate.set(year, month, day)
updateDateFields()
,
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH)
)
datePicker.show()
private fun updateDateFields()
val formatter = SimpleDateFormat("MMM dd, yyyy", Locale.getDefault())
val invoiceDueDt = findViewById<TextView>(R.id.invoiceDueDt)
if(dueDate.time < Calendar.getInstance().time)
Toast.makeText(this, "Please select a date that is today or later", Toast.LENGTH_SHORT).show()
else
invoiceDueDt.text = formatter.format(dueDate.time)
private fun editInvoice()
val invoiceTitle = findViewById<EditText>(R.id.invoiceTitle)
val invoiceClient = findViewById<AutoCompleteTextView>(R.id.invoiceClient)
val itemOtherDetails = findViewById<EditText>(R.id.itemOtherDetails)
if(invoice!!.invoiceTitle != "0")
invoiceTitle.setText(invoice!!.invoiceTitle)
if(invoice!!.invoiceClientLKey != "0")
//getting client name from the database
val getClient = AppDatabase.getDatabase(this)
contact = getClient.contactsDao().getSingleContact(invoice!!.invoiceClientLKey!!)
invoiceClient.setText(contact.name)
if(invoice!!.othComments != "0")
itemOtherDetails.setText(invoice!!.othComments)
addinvoiceItem()
invoiceClient.setOnClickListener
val intent = Intent(this, ContactDetailsHome::class.java)
intent.putExtra("contact", contact as Serializable)
this.startActivity(intent)
private fun addinvoiceItem()
val invoiceItemsLayout = findViewById<RelativeLayout>(R.id.invoiceItemsLayout)
val invoiceSubValue = findViewById<TextView>(R.id.invoiceSubValue)
val invoiceTaxValue = findViewById<TextView>(R.id.invoiceTaxValue)
val invoiceTotalValue = findViewById<TextView>(R.id.invoiceTotalValue)
if(invoice != null)
if(intent.getSerializableExtra("invoiceItem") == null)
//getting invoice items stored in the local db
val getItems = AppDatabase.getDatabase(this)
invoiceItems = getItems.InvoiceItemsDao().getinvItem(invoice!!.invNo)
for (i in invoiceItems!!.indices+1)
//Check if invoiceItems have been received from EditBillingItems if yes, then update the particular object
if(j == i)
invoiceItems!![i].itemTitle = invoiceUpdt!!.itemTitle
invoiceItems!![i].itemDesc = invoiceUpdt!!.itemDesc
invoiceItems!![i].itemQty = invoiceUpdt!!.itemQty
invoiceItems!![i].itemRate = invoiceUpdt!!.itemRate
invoiceItems!![i].itemTaxable = invoiceUpdt!!.itemTaxable
invoiceItems!![i].itemTotal = invoiceUpdt!!.itemTotal
//Item Name Display on Invoice Activity
val itemTitle: ArrayList<TextView>? = null
itemTitle!![i] = TextView(this)
val layoutParams: RelativeLayout.LayoutParams = RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT
) // or wrap_content
layoutParams.setMargins(0, 0, 0, 0)
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_START)
itemTitle[i].hint = "Enter Item Title"
itemTitle[i].textSize = 16f
itemTitle[i].layoutParams = layoutParams
itemTitle[i].setTextColor(resources.getColor(R.color.txtcolor))
invoiceItemsLayout.addView(itemTitle[i])
itemTitle[i].text = invoiceItems!![i].itemTitle
//Total Item Value
val itemValue: ArrayList<TextView>? = null
itemValue!![i] = TextView(this)
val layoutParams2: RelativeLayout.LayoutParams = RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT
) // or wrap_content
layoutParams2.setMargins(0, 0, 0, 0)
layoutParams2.addRule(RelativeLayout.ALIGN_PARENT_END)
itemValue[i].text = "00.00"
itemValue[i].textSize = 16f
itemValue[i].setTextColor(resources.getColor(R.color.txtcolor))
itemValue[i].setPadding(10, 0, 0, 10)
itemValue[i].layoutParams = layoutParams2
invoiceItemsLayout.addView(itemValue[i], layoutParams)
itemValue[i].text = invoiceItems!![i].itemTotal.toString()
if(invoiceItems!![i + 1].itemTitle == "")
//New Item Title field
val itemTitle: ArrayList<TextView>? = null
itemTitle!![i] = TextView(this)
val layoutParams: RelativeLayout.LayoutParams = RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT
) // or wrap_content
layoutParams.setMargins(0, 0, 0, 0)
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_START)
itemTitle[i].hint = "Enter Item Title"
itemTitle[i].textSize = 16f
itemTitle[i].setTextColor(resources.getColor(R.color.txtcolor))
invoiceItemsLayout.addView(itemTitle[i], layoutParams)
//New item value field
val itemValue: ArrayList<TextView>? = null
itemValue!![i] = TextView(this)
val layoutParams2: RelativeLayout.LayoutParams = RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT
) // or wrap_content
layoutParams2.setMargins(0, 0, 0, 0)
layoutParams2.addRule(RelativeLayout.ALIGN_PARENT_END)
itemValue[i].text = "00.00"
itemValue[i].textSize = 16f
itemValue[i].setTextColor(resources.getColor(R.color.txtcolor))
itemValue[i].setPadding(10, 0, 0, 10)
itemValue[i].layoutParams = layoutParams2
invoiceItemsLayout.addView(itemValue[i], layoutParams)
itemTitle[i].setOnClickListener
val invoiceItemSend: InvoiceItems = invoiceItems!![i]
updateInvoiceValues()
val intent = Intent(this, EditBillingItem::class.java)
intent.putExtra("invoiceItem", invoiceItems as Serializable)
intent.putExtra("index", i)
intent.putExtra("invoice", invoice as Serializable)
this.startActivity(intent)
subTotal += invoiceItems!![i].itemTotal
val taxValue = invoiceItems!![i].itemRate!!
taxrate += (subTotal * taxValue)
invoiceSubValue.setText(subTotal)
total = subTotal + taxrate
invoiceTaxValue.setText(taxrate)
invoiceTotalValue.setText(total)
else
//Item Name Display on Invoice Activity
val layoutParams: RelativeLayout.LayoutParams = RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT
) // or wrap_content
layoutParams.setMargins(0, 0, 0, 0)
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_START)
val itemTitle = TextView(this)
itemTitle.hint = "Enter Item Title"
itemTitle.textSize = 16f
itemTitle.setTextColor(resources.getColor(R.color.txtcolor))
invoiceItemsLayout.addView(itemTitle, layoutParams)
//Total Item Value
val itemValue = TextView(this)
val layoutParams2: RelativeLayout.LayoutParams = RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT
) // or wrap_content
layoutParams2.setMargins(0, 0, 0, 0)
layoutParams2.addRule(RelativeLayout.ALIGN_PARENT_END)
itemValue.text = "00.00"
itemValue.textSize = 16f
itemValue.setTextColor(resources.getColor(R.color.txtcolor))
itemValue.setPadding(10, 0, 0, 10)
itemValue.layoutParams = layoutParams2
invoiceItemsLayout.addView(itemValue, layoutParams2)
itemTitle.setOnClickListener
updateInvoiceValues()
val intent = Intent(this, EditBillingItem::class.java)
if(invoiceItems != null)
intent.putExtra("invoiceItem", invoiceItems as Serializable)
if(invoice != null)
intent.putExtra("invoice", invoice as Serializable)
intent.putExtra("index",0)
this.startActivity(intent)
private fun updateInvoiceValues()
//updating values
val invoiceTitle = findViewById<EditText>(R.id.invoiceTitle)
val invoiceDueDt = findViewById<TextView>(R.id.invoiceDueDt)
if(invoiceTitle.text.toString().isNotEmpty())
invoiceEdit?.invoiceTitle = invoiceTitle.text.toString()
if(clientLkey != "")
invoiceEdit?.invoiceClientLKey = clientLkey
if (invoiceDueDt.text.toString().isNotEmpty())
invoiceEdit?.dueDate = invoiceDueDt.text.toString()
活动 B - 编辑项目
class EditBillingItem : AppCompatActivity()
companion object
@JvmStatic
fun start(context: Context, invoice: Invoice?, invoiceItems: InvoiceItems?)
val i = 0
val starter = Intent(context, EditInvoice::class.java)
.putExtra("invoice", invoice)
.putExtra("invoiceItem", invoiceItems)
.putExtra("i", i)
context.startActivity(starter)
private var invoiceItem: List<InvoiceItems>? = null
private var invoice: Invoice? = null
private lateinit var invoiceItemUpdt: InvoiceItems
private var i = 0
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_billing_item_update)
invoice = intent.getSerializableExtra("invoiceEdit") as Invoice
invoiceItem = intent.getSerializableExtra("invoiceItem") as? List<InvoiceItems>
i = intent.getIntExtra("i", i)
val itemTitle = findViewById<EditText>(R.id.itemTitle)
val itemDesc = findViewById<EditText>(R.id.itemDesc)
val itemQty = findViewById<EditText>(R.id.itemQty)
val itemChrgRt = findViewById<EditText>(R.id.itemChrgRt)
val itemTaxable = findViewById<SwitchCompat>(R.id.itemTaxable)
val itemTotal = findViewById<TextView>(R.id.itemTotal)
val itemBack = findViewById<ImageButton>(R.id.itemBack)
if(intent.getSerializableExtra("invoiceItems") != null)
itemTitle.setText(invoiceItem!![i].itemTitle)
itemDesc.setText(invoiceItem!![i].itemDesc)
itemQty.setText(invoiceItem!![i].itemQty.toString())
itemChrgRt.setText(invoiceItem!![i].itemRate.toString())
itemTaxable.isChecked = invoiceItem!![i].itemTaxable == true
itemTotal.setText(invoiceItem!![i].itemTotal)
itemChrgRt.addTextChangedListener(object : TextWatcher
override fun afterTextChanged(s: Editable)
override fun beforeTextChanged(s: CharSequence, start: Int,
count: Int, after: Int)
override fun onTextChanged(s: CharSequence, start: Int,
before: Int, count: Int)
if(s.toString().isNotEmpty() && itemQty.text.toString().isNotEmpty())
var i = itemQty.text.toString().toInt()
val j = s.toString().toInt()
i *= j
itemTotal.text = i.toString()
)
itemQty.addTextChangedListener(object : TextWatcher
override fun afterTextChanged(s: Editable)
override fun beforeTextChanged(s: CharSequence, start: Int,
count: Int, after: Int)
override fun onTextChanged(s: CharSequence, start: Int,
before: Int, count: Int)
if(itemChrgRt.text.toString().isNotEmpty() && itemChrgRt.text.toString().isNotEmpty())
var i = s.toString().toInt()
val j = itemChrgRt.text.toString().toInt()
i *= j
itemTotal.text = i.toString()
)
itemBack.setOnClickListener
if(itemTitle.toString().isBlank() && itemQty.toString().isNotBlank() || itemChrgRt.toString().isNotBlank() && itemTitle.toString().isBlank())
Toast.makeText(this, "Title can't be empty", Toast.LENGTH_SHORT).show()
return@setOnClickListener
invoiceItemUpdt = InvoiceItems("0","0","0",null,null,null,null,0)
invoiceItemUpdt.itemTitle = itemTitle.toString()
invoiceItemUpdt.itemTitle = itemDesc.toString()
if(itemQty.toString().isEmpty())
invoiceItemUpdt.itemQty = 1
else
invoiceItemUpdt.itemQty = itemQty.text.toString().toInt()
invoiceItemUpdt.itemRate = itemChrgRt.text.toString().toInt()
itemTaxable.isChecked = invoiceItemUpdt.itemTaxable == true
val intent = Intent(this, EditInvoice::class.java)
intent.putExtra("invoice", invoice as Serializable)
intent.putExtra("invoiceItem", invoiceItem as Serializable)
intent.putExtra("invoiceItemUpdt", invoiceItemUpdt as Serializable)
intent.putExtra("index", i)
this.startActivity(intent)
来自 logcat 的错误 java.lang.NullPointerException:null 不能转换为非 null 类型 java.io.Serializable 在 in.latom.latom.Billing.ui.EditInvoice$addinvoiceItem$2.onClick(EditInvoice.kt:449) 在 android.view.View.performClick(View.java:7398) 在 android.view.View.performClickInternal(View.java:7375) 在 android.view.View.access$3700(View.java:817) 在 android.view.View$PerformClick.run(View.java:28516) 在 android.os.Handler.handleCallback(Handler.java:938) 在 android.os.Handler.dispatchMessage(Handler.java:99) 在 android.os.Looper.loopOnce(Looper.java:201) 在 android.os.Looper.loop(Looper.java:288) 在 android.app.ActivityThread.main(ActivityThread.java:7858) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:984)
【问题讨论】:
请显示错误日志 【参考方案1】:如果此行返回 null,您的 invoice
变量将为 null:
invoice = intent.getSerializableExtra("invoice") as? Invoice
稍后在您的代码中,您从未填充过您的 invoice
变量,但您在这一行中强制将其展开:
db.InvoicesDao().addInvoice(invoice!!)
此 if 语句始终为空:
if(invoice != null)
intent.putExtra("invoice", invoice as Serializable)
【讨论】:
您好,根据您的输入,我将代码修改如下 if (invoice == null) invoiceType = "new" edit_inv.text = "Add Invoice" invoiceEdit = Invoice("0", "0","0","0","0","0",0,0,null,"") addinvoiceItem() else invoiceEdit = invoice editInvoice() 。但是在我将数据添加到 invoiceEdit 并将其发送到下一个活动后,它仍然被识别为 null....你怎么看? 已使用我编辑项目的活动代码更新了问题,并且还共享了空指针错误... 检查这一行:EditInvoice.kt:449 intent.putExtra("invoiceItem", invoiceItems as Serializable) - 不知道为什么这是个问题?我收到它是这样的 invoiceItem = intent.getSerializableExtra("invoiceItem") 吗?列表以上是关于在保存之前初始化空对象并在活动之间传递的主要内容,如果未能解决你的问题,请参考以下文章
从 stackview 小部件传递可序列化对象会产生空指针异常
CoreData NSManagingContextDidSaveChangesNotification 保存空对象iOS5