当我的数据从服务器获取时,我试图显示CircularProgressIndicator
,但我得到了这个错误root.findViewById(R.id.loadingbar) must not be null
。
逻辑
- 在提取数据之前隐藏回收器视图项目
- 提取数据时显示
Circular Progress
- 数据准备就绪时隐藏
Circular Progress
- 显示可回收查看的项目
代码
xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<!-- Circular progress indicator -->
<com.google.android.material.progressindicator.CircularProgressIndicator
android:id="@+id/loadingbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
android:layout_gravity="center" />
<!-- RecyclerView items -->
<androidx.cardview.widget.CardView
android:id="@+id/cardView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:elevation="8dp">
<TextView
android:id="@+id/order_Iid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:gravity="start|top"
android:text="@string/order_ID"
android:textSize="12sp"
android:textStyle="bold" />
<TextView
android:id="@+id/order_status_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|start"
android:layout_marginStart="5dp"
android:layout_marginTop="35dp"
android:text="@string/order_status"
android:textColor="#5CDCBD"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/order_price_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|end"
android:layout_marginEnd="5dp"
android:text="@string/price"
android:textSize="12sp"
android:textStyle="bold" />
</androidx.cardview.widget.CardView>
</LinearLayout>
Fragment
为了更好地理解,对代码进行了注释
class OrdersFragment : Fragment() {
lateinit var sesssion: SessionManager
lateinit var laundriesRecycler: RecyclerView
lateinit var progressBar: CircularProgressIndicator
lateinit var cardView2: CardView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val root = inflater.inflate(R.layout.fragment_orders, container, false)
sesssion = SessionManager(context)
laundriesRecycler = root.findViewById(R.id.orders_list)
// get progress
progressBar = root.findViewById(R.id.loadingbar)
//get recycler item
cardView2 = root.findViewById(R.id.cardView2)
getOrders()
return root
}
private fun getOrders() {
//show progress
progressBar.visibility = View.VISIBLE
//hide items
cardView2.visibility = View.GONE
var session = SessionManager(context)
session.checkLogin()
var user = session.getUserDetails()
var token: String? = user.get(SessionManager.KEY_ACCESS_TOKEN)
val tokenFull = "Bearer $token"
val queue = Volley.newRequestQueue(context)
val url = "https://example.com/api/orders"
val stringReq : StringRequest =
object : StringRequest(
Method.GET, url,
Response.Listener { response ->
// hide progress
progressBar.visibility = View.GONE
//show items
cardView2.visibility = View.VISIBLE
val list = Gson().fromJson(response, OrderArr::class.java)
laundriesRecycler.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
laundriesRecycler.adapter = OrdersAdapter(context, list)
},
Response.ErrorListener { error ->
Toast.makeText(context, error.message, Toast.LENGTH_LONG)
.show()
}
){
override fun getHeaders(): Map<String, String> {
val headers = HashMap<String, String>()
headers["Content-Type"] = "application/json"
headers["Authorization"] = tokenFull
return headers
}
}
queue.add(stringReq)
}
}
知道吗
在构建.gradle(应用程序(时
android{
buildFeatures {
viewBinding = true
dataBinding = true
}
}
// 1 - direct inflate the fragment layout into Fragment()
class OrdersFragment : Fragment(R.layout.fragment_orders) {
// 2 - view binding
private lateinit var binding: FragmentOrdersBinding
lateinit var sesssion: SessionManager
lateinit var laundriesRecycler: RecyclerView
lateinit var progressBar: CircularProgressIndicator
lateinit var cardView2: CardView
// 3 - directly call onViewCreated() as the layout already inflated
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
// 4 - bind view to viewBinding variable
binding = FragmentOrdersBinding.bind(view)
sesssion = SessionManager(context)
getOrders()
}
private fun getOrders() {
// 5 - After that, basically every element just call binding to locate them
//show progress
binding.loadingBar.visibility = View.VISIBLE
//hide items
binding.cardView2.visibility = View.GONE
}
}
已解决
特别感谢Teo
,他让我意识到了这个问题。
Fixes
- 我没有把我的进度放在我的项目xml中,而是把它添加到我的碎片xml中,我的回收器代码放在那里(#1放错地方的代码(
- 使用绑定(与前面提到的Teo不同,不需要使用导致未定义
binding
错误的onViewCreated
infact。相反,它应该在onCreateView
函数中定义(以下是最终代码
private lateinit var binding: FragmentOrdersBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val root = inflater.inflate(R.layout.fragment_orders, container, false)
sesssion = SessionManager(context)
laundriesRecycler = root.findViewById(R.id.orders_list)
binding = FragmentOrdersBinding.bind(root) // <--here
getOrders()
return root
}
private fun getOrders() {
binding.loadingBar.visibility = View.VISIBLE
binding.ordersList.visibility = View.GONE
// API process and flip those 2 lines above in success response to
binding.loadingBar.visibility = View.GONE
binding.ordersList.visibility = View.VISIBLE
}