我正在尝试创建一个Android应用,该应用的数据在Firebase realtimeDatabase中可用。现在,我想添加一个预加载器文本,以使访问者不会出错(加载时没有任何数据)。我尝试使用线程,这是可以的,但是在加载数据时出现了问题。加载应用程序数据后,显示“不幸的是您的应用程序已停止”的应用程序(在隐藏加载程序文本之前,应用程序弯曲)。直到未加载应用程序数据,应用程序显示加载程序文本,但加载数据后,加载程序文本未隐藏并且应用程序崩溃。哪里错了?
package com.abdullah.md.allsimoffers;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;
import com.google.android.gms.ads.MobileAds;
import com.google.firebase.database.ChildEventListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import java.util.ArrayList;
public class SecondActivity extends AppCompatActivity {
DatabaseReference dref;
ListView listview;
ArrayList<String> list = new ArrayList<>();
ArrayList<String> keyCheck = new ArrayList<>();
Bundle bundle;
String title;
private AdView adView;
private AdRequest adRequest;
TextView preloader;
ArrayAdapter<String> adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
MobileAds.initialize(this, "ca-app-pub-3940256099942544~3347511713");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
preloader = findViewById(R.id.preloaderId);
adView = (AdView) findViewById(R.id.adViewId);
adRequest = new AdRequest.Builder().build();
adView.loadAd(adRequest);
listview = findViewById(R.id.listViewId);
adapter = new ArrayAdapter<String>(this, R.layout.custom_layout, R.id.headingTextViewId, list);
listview.setAdapter(adapter);
bundle = getIntent().getExtras();
if (bundle != null) {
String intentValue = bundle.getString("intentValue");
if (intentValue.contains("banglalink")) {
dref = FirebaseDatabase.getInstance().getReferenceFromUrl("https://allsimoffers.firebaseio.com/banglalink");
title = "Banglalink";
} else if (intentValue.contains("grameenphone")) {
dref = FirebaseDatabase.getInstance().getReferenceFromUrl("https://allsimoffers.firebaseio.com/grameenphone");
title = "grameenPhone";
} else if (intentValue.contains("robi")) {
dref = FirebaseDatabase.getInstance().getReferenceFromUrl("https://allsimoffers.firebaseio.com/robi");
title = "Robi";
} else if (intentValue.contains("airtel")) {
dref = FirebaseDatabase.getInstance().getReferenceFromUrl("https://allsimoffers.firebaseio.com/airtel");
title = "Airtel";
} else if (intentValue.contains("teletalk")) {
dref = FirebaseDatabase.getInstance().getReferenceFromUrl("https://allsimoffers.firebaseio.com/teletalk");
title = "Teletalk";
}
}
getSupportActionBar().setTitle(title);
new preloaderClass().execute();
//---------------------------onCreate method end--------------------------
}
class preloaderClass extends AsyncTask<Void,Void, ArrayList<String>> {
@Override
protected void onPreExecute() {
listview.setVisibility(View.GONE);
preloader.setVisibility(View.VISIBLE);
super.onPreExecute();
}
@Override
protected ArrayList<String> doInBackground(Void... voids) {
dref.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
list.add(dataSnapshot.getValue(String.class));
keyCheck.add(dataSnapshot.getKey());
adapter.notifyDataSetChanged();
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
String value = dataSnapshot.getValue(String.class);
String key = (dataSnapshot.getKey());
int valueOfKey = keyCheck.indexOf(key);
list.set(valueOfKey, value);
adapter.notifyDataSetChanged();
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
list.remove(dataSnapshot.getValue(String.class));
keyCheck.remove(dataSnapshot.getKey());
adapter.notifyDataSetChanged();
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(SecondActivity.this, databaseError.toException().toString(), Toast.LENGTH_SHORT).show();
}
});
return list;
}
@Override
protected void onPostExecute(ArrayList<String> strings) {
if (!strings.isEmpty()){
listview.setVisibility(View.VISIBLE);
preloader.setVisibility(View.GONE);
}
else if (strings.isEmpty()){
Toast.makeText(SecondActivity.this, "Failed", Toast.LENGTH_SHORT).show();
}
super.onPostExecute(strings);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.options_menu, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.homeMenuId) {
Intent intent = new Intent(this, FirstActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
} else if (item.getItemId() == R.id.aboutMenuId) {
Intent intent = new Intent(this, ThirdActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
} else if (item.getItemId() == android.R.id.home) {
Intent intent = new Intent(this, FirstActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
}
return super.onOptionsItemSelected(item);
}
// ---------------------选项菜单结束--------------------- -----------------
}
答案 0 :(得分:0)
您永远不要从后台线程访问UI元素(例如预加载器)。您的应用程序由于尝试访问UI元素而不是main thread
而崩溃。
要修复您的代码,您可以致电
runOnUiThread(new Runnable(){
preloader.setVisibility(View.GONE);
})
但我真的鼓励您检查在后台加载数据的适当方法,以从后台线程更新UI。选中AsyncTask
,IntentService
,ThreadPools
,RxJava
,Coroutines
。
同样从您的代码中,为什么每次都需要检查list
,为什么在创建/更新list
后就不能删除预加载器
已更新: 我并不是说您需要后台线程。 Firebase侦听器已在主线程中调用。检查一下:
public class SecondActivity extends AppCompatActivity implements ChildEventListener {
DatabaseReference dref;
ListView listview;
ArrayList<String> list = new ArrayList<>();
ArrayList<String> keyCheck = new ArrayList<>();
Bundle bundle;
String title;
private AdView adView;
private AdRequest adRequest;
TextView preloader;
ArrayAdapter<String> adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
MobileAds.initialize(this, "ca-app-pub-3940256099942544~3347511713");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
preloader = findViewById(R.id.preloaderId);
adView = (AdView) findViewById(R.id.adViewId);
adRequest = new AdRequest.Builder().build();
adView.loadAd(adRequest);
listview = findViewById(R.id.listViewId);
adapter = new ArrayAdapter<String>(this, R.layout.custom_layout, R.id.headingTextViewId, list);
listview.setAdapter(adapter);
bundle = getIntent().getExtras();
if (bundle != null) {
String intentValue = bundle.getString("intentValue");
if (intentValue.contains("banglalink")) {
dref = FirebaseDatabase.getInstance().getReferenceFromUrl("https://allsimoffers.firebaseio.com/banglalink");
title = "Banglalink";
} else if (intentValue.contains("grameenphone")) {
dref = FirebaseDatabase.getInstance().getReferenceFromUrl("https://allsimoffers.firebaseio.com/grameenphone");
title = "grameenPhone";
} else if (intentValue.contains("robi")) {
dref = FirebaseDatabase.getInstance().getReferenceFromUrl("https://allsimoffers.firebaseio.com/robi");
title = "Robi";
} else if (intentValue.contains("airtel")) {
dref = FirebaseDatabase.getInstance().getReferenceFromUrl("https://allsimoffers.firebaseio.com/airtel");
title = "Airtel";
} else if (intentValue.contains("teletalk")) {
dref = FirebaseDatabase.getInstance().getReferenceFromUrl("https://allsimoffers.firebaseio.com/teletalk");
title = "Teletalk";
}
}
getSupportActionBar().setTitle(title);
}
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
list.add(dataSnapshot.getValue(String.class));
keyCheck.add(dataSnapshot.getKey());
adapter.notifyDataSetChanged();
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
String value = dataSnapshot.getValue(String.class);
String key = (dataSnapshot.getKey());
int valueOfKey = keyCheck.indexOf(key);
list.set(valueOfKey, value);
adapter.notifyDataSetChanged();
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
list.remove(dataSnapshot.getValue(String.class));
keyCheck.remove(dataSnapshot.getKey());
adapter.notifyDataSetChanged();
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(SecondActivity.this, databaseError.toException().toString(), Toast.LENGTH_SHORT).show();
}
private void updateUI() {
if (!list.isEmpty()) {
listview.setVisibility(View.VISIBLE);
preloader.setVisibility(View.GONE);
} else {
listview.setVisibility(View.GONE);
preloader.setVisibility(View.VISIBLE);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.options_menu, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.homeMenuId) {
Intent intent = new Intent(this, FirstActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
} else if (item.getItemId() == R.id.aboutMenuId) {
Intent intent = new Intent(this, ThirdActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
} else if (item.getItemId() == android.R.id.home) {
Intent intent = new Intent(this, FirstActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
}
return super.onOptionsItemSelected(item);
}
}