Ich mache ein Abstimmungssystem in einer Android-App, die Firebase als Backend verwendet. Ich bin dabei, den Abstimmungsstatus des Benutzers anhand seines Verlaufs zu ermitteln, die Ansicht entsprechend zu aktualisieren und auf die Berührungen der Schaltfläche zu reagieren. Das Problem, das ich habe, ist, dass, wenn ein Benutzer auf die Hoch- oder Runter-Schaltfläche klickt, die Listenansicht neu gezeichnet wird, wobei manchmal zwei der Optionen weggelassen werden und das Scrollen der Ansicht immer wieder nach oben verschoben wird. Kann ich die Daten in einer Listenansicht aktualisieren, ohne diese Listenansicht vollständig neu zu zeichnen? Wenn das so ist, wie?update firebase info ohne redrapping listview
MovieActivity.java
public class MovieActivity extends AppCompatActivity {
private static final String KEY_IMDB = "KEY_IMDB";
private ImageView mPosterImageView;
private TextView mTitleTextView;
private TextView mYearTextView;
private TextView mSummaryTextView;
private ListView triggerListView;
private ArrayList<Trigger> mTriggerPrefList;
private Movie mMovie;
private LinkedList<Trigger> resultList;
DatabaseReference movieDB;
DatabaseReference userDB;
DatabaseReference thisMovieDB;
DatabaseReference triggerDB;
DatabaseReference adminDB;
FirebaseAuth mFirebaseAuth;
FirebaseUser mUser;
ArrayList<Trigger> mTriggerList;
String imdbID;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_movie);
mPosterImageView = (ImageView) findViewById(R.id.posterImageView);
mTitleTextView = (TextView) findViewById(R.id.titleTextView);
mYearTextView = (TextView) findViewById(R.id.yearTextView);
mSummaryTextView = (TextView) findViewById(R.id.summaryTextView);
triggerListView = (ListView) findViewById(R.id.triggerListView);
mFirebaseAuth = FirebaseAuth.getInstance();
mUser = mFirebaseAuth.getCurrentUser();
movieDB = FirebaseDatabase.getInstance().getReference("movies");
userDB = FirebaseDatabase.getInstance().getReference("users");
adminDB = FirebaseDatabase.getInstance().getReference("admin");
Intent intent = getIntent();
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
imdbID = intent.getStringExtra("ID_KEY");
final String keyTitle = intent.getStringExtra("TITLE_KEY");
final String keyYear = intent.getStringExtra("YEAR_KEY");
final String keyPoster = intent.getStringExtra("POSTER_KEY");
try {
getMovieDetails(imdbID, new Runnable() {
@Override
public void run() {
CheckForTriggerValues(new Runnable() {
@Override
public void run() {
populateTriggers(new Runnable() {
@Override
public void run() {
populatePrefs(new Runnable() {
@Override
public void run() {
reOrderList(new Runnable() {
@Override
public void run() {
Movie passMovie = new Movie();
passMovie.setImdbID(imdbID);
passMovie.setPosterURL(keyPoster);
passMovie.setYear(keyYear);
passMovie.setTitle(keyTitle);
TriggerAdapter adapter = new TriggerAdapter(MovieActivity.this, resultList, passMovie, imdbID);
triggerListView.setAdapter(adapter);
}
});
}
});
}
});
}
});
}
});
} catch (JSONException e) {
e.printStackTrace();
}
thisMovieDB = movieDB.child(imdbID);
triggerDB = thisMovieDB.child("Triggers");
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(KEY_IMDB, imdbID);
}
@Override
protected void onStart() {
super.onStart();
Intent intent = getIntent();
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
imdbID = intent.getStringExtra("ID_KEY");
}
private void getMovieDetails(String imdbID, Runnable runnable) throws JSONException {
String apiKey = OMITTED;
String theURL = "http://www.omdbapi.com/?i=" + imdbID + "&apikey=" + apiKey;
final OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(theURL).build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
final String jsonData = response.body().string();
if (response.isSuccessful()) {
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
Movie movie = parseMovieDetails(jsonData);
updateMovieUI(movie);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
}
});
runnable.run();
}
private Movie parseMovieDetails(String jsonData) throws JSONException {
JSONObject jsonObject = new JSONObject(jsonData);
Movie movie = new Movie();
movie.setPosterURL(jsonObject.getString("Poster"));
movie.setTitle(jsonObject.getString("Title"));
movie.setYear(jsonObject.getString("Year"));
movie.setSummary(jsonObject.getString("Plot"));
mMovie = movie;
return movie;
}
private void updateMovieUI(Movie movie){
Context mContext = getApplicationContext();
mSummaryTextView.setText(movie.getSummary());
mYearTextView.setText(movie.getYear());
mTitleTextView.setText(movie.getTitle());
Picasso.with(mContext).load(movie.getPosterURL()).into(mPosterImageView);
}
private void populatePrefs(final Runnable runnable) {
mTriggerPrefList = new ArrayList<>();
mFirebaseAuth = FirebaseAuth.getInstance();
mUser = mFirebaseAuth.getCurrentUser();
movieDB = FirebaseDatabase.getInstance().getReference("movies");
userDB = FirebaseDatabase.getInstance().getReference("users");
adminDB = FirebaseDatabase.getInstance().getReference("admin");
thisMovieDB = movieDB.child(imdbID);
thisMovieDB.child("Details").setValue(mMovie);
triggerDB = thisMovieDB.child("Triggers");
userDB.child(mUser.getUid()).child("preferences").child("trigger").addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot triggerSnapshot : dataSnapshot.getChildren()) {
String name = String.valueOf(triggerSnapshot.child("triggerName").getValue());
Trigger trigger = new Trigger();
trigger.setTriggerName(name);
trigger.setTriggerVotesTotal(0);
trigger.setTriggerVotesYes(0);
mTriggerPrefList.add(trigger);
}
Intent intent = getIntent();
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
imdbID = intent.getStringExtra("ID_KEY");
runnable.run();
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private void populateTriggers(final Runnable runnable) {
mTriggerList = new ArrayList<>();
mFirebaseAuth = FirebaseAuth.getInstance();
mUser = mFirebaseAuth.getCurrentUser();
movieDB = FirebaseDatabase.getInstance().getReference("movies");
userDB = FirebaseDatabase.getInstance().getReference("users");
adminDB = FirebaseDatabase.getInstance().getReference("admin");
thisMovieDB = movieDB.child(imdbID);
thisMovieDB.child("Details").setValue(mMovie);
triggerDB = thisMovieDB.child("Triggers");
triggerDB.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
mTriggerList.clear();
for (DataSnapshot triggerSnapshot : dataSnapshot.getChildren()) {
Trigger trigger = triggerSnapshot.getValue(Trigger.class);
mTriggerList.add(trigger);
}
runnable.run();
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private void reOrderList(Runnable runnable) {
resultList = new LinkedList<>();
for (Trigger triggerA : mTriggerList) {
boolean found = false;
for (Trigger triggerB : mTriggerPrefList) {
if (triggerB.getTriggerName().equals(triggerA.getTriggerName())) {
found = true;
}
}
if (found) {
resultList.add(triggerA);
}
}
mTriggerList.removeAll(resultList);
resultList.addAll(mTriggerList);
runnable.run();
}
private void CheckForTriggerValues(final Runnable runnable) {
adminDB.child("triggerList").addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
GenericTypeIndicator<Map<String, Object>> genericTypeIndicator = new GenericTypeIndicator<Map<String, Object>>() {};
final Map<String, Object> triggerList = dataSnapshot.getValue(genericTypeIndicator);
triggerDB.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (Map.Entry<String, Object> entry : triggerList.entrySet())
{
if (dataSnapshot.hasChild(entry.getKey())){
}
else {
Trigger trigger1 = new Trigger(entry.getKey(), 0, 0);
triggerDB.child(trigger1.getTriggerName()).setValue(trigger1);
}
}
runnable.run();
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
int isTrue(Boolean boolDown, Boolean boolUp) {
int x = 0;
if (boolUp) {
x = 1;
}
if (boolDown) {
x = -1;
}
return x;
}
}
TriggerAdapter.java
package me.paxana.cwnet.Adapters;
import android.app.Activity;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Typeface;
import android.os.Build;
import android.provider.ContactsContract;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.TextView;
import com.andremion.counterfab.CounterFab;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
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 com.google.firebase.database.MutableData;
import com.google.firebase.database.Transaction;
import com.google.firebase.database.ValueEventListener;
import java.util.List;
import me.paxana.cwnet.Model.Movie;
import me.paxana.cwnet.Model.Trigger;
import me.paxana.cwnet.R;
import me.paxana.cwnet.ui.AdminPanelActivity;
import me.paxana.cwnet.ui.MovieActivity;
/**
* Created by paxie on 10/11/17.
*/
public class TriggerAdapter extends BaseAdapter {
private Context mContext;
private List<Trigger> mTriggers;
private Movie mMovie;
private String mImdbID;
private String mTitle;
private String mYear;
private String mPosterURL;
private DatabaseReference movieDB;
private DatabaseReference userDB;
private DatabaseReference triggerDB;
private DatabaseReference adminDB;
public TriggerAdapter(Context context, List<Trigger> triggerList, Movie movie, String imdbID){
mContext = context;
this.mTriggers = triggerList;
mMovie = movie;
mImdbID = imdbID;
mTitle = movie.getTitle();
mYear = movie.getYear();
mPosterURL = movie.getPosterURL();
};
public TriggerAdapter(Context context, List<Trigger> triggerList) {
mContext = context;
this.mTriggers = triggerList;
}
@Override
public int getCount() {
return this.mTriggers.size();
}
@Override
public Object getItem(int i) {
return mTriggers.get(i);
}
@Override
public long getItemId(int i) {
return 0;
}
@Override
public View getView(int i, View view, final ViewGroup viewGroup) {
final ViewHolder holder;
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
FirebaseUser user = firebaseAuth.getCurrentUser();
movieDB = FirebaseDatabase.getInstance().getReference("movies");
userDB = FirebaseDatabase.getInstance().getReference("users");
adminDB = FirebaseDatabase.getInstance().getReference("admin");
final String mUserId = user.getUid();
final Trigger trigger = mTriggers.get(i);
if (view == null) {
view = LayoutInflater.from(mContext).inflate(R.layout.trigger_list_item, null);
holder = new ViewHolder();
holder.triggerName = view.findViewById(R.id.triggerName);
holder.upButton = view.findViewById(R.id.mTriggerButtonUp);
holder.downButton = view.findViewById(R.id.mTriggerButtonDown);
holder.total = view.findViewById(R.id.triggerCounter);
view.setTag(holder);
}
else {
holder = (ViewHolder) view.getTag();
}
holder.triggerName.setText(trigger.getTriggerName());
if (mContext instanceof AdminPanelActivity) {
holder.upButton.setVisibility(View.INVISIBLE);
holder.downButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
adminDB.child("triggerList").child(trigger.getTriggerName()).removeValue();
int i = mTriggers.indexOf(trigger);
mTriggers.remove(i);
TriggerAdapter.this.notifyDataSetChanged();
}
});
}
if (mContext instanceof MovieActivity) {
userDB.child(mUserId).child("changes").child(mImdbID).child("triggers").child(trigger.getTriggerName()).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.getValue() != null) {
int userVote = dataSnapshot.getValue(Integer.class);
if (userVote == 0) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
holder.upButton.setBackgroundTintList(mContext.getResources().getColorStateList(R.color.colorAccent, null));
holder.downButton.setBackgroundTintList(mContext.getResources().getColorStateList(R.color.colorAccent, null));
}
else {
holder.upButton.setBackgroundTintList(mContext.getResources().getColorStateList(R.color.colorAccent));
holder.downButton.setBackgroundTintList(mContext.getResources().getColorStateList(R.color.colorAccent));
}
neitherButtonIsSelected(holder, trigger, mUserId);
}
if (userVote == 1) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
holder.upButton.setBackgroundTintList(mContext.getResources().getColorStateList(R.color.votebuttons, null));
holder.downButton.setBackgroundTintList(mContext.getResources().getColorStateList(R.color.colorAccent, null));
}
else {
holder.upButton.setBackgroundTintList(mContext.getResources().getColorStateList(R.color.votebuttons));
holder.downButton.setBackgroundTintList(mContext.getResources().getColorStateList(R.color.colorAccent));
}
upButtonIsSelected(holder, trigger, mUserId);
}
if (userVote == -1) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
holder.upButton.setBackgroundTintList(mContext.getResources().getColorStateList(R.color.colorAccent, null));
holder.downButton.setBackgroundTintList(mContext.getResources().getColorStateList(R.color.votebuttons, null));
}
else {
holder.upButton.setBackgroundTintList(mContext.getResources().getColorStateList(R.color.colorAccent));
holder.downButton.setBackgroundTintList(mContext.getResources().getColorStateList(R.color.votebuttons));
}
downButtonIsSelected(holder, trigger, mUserId);
}
}
else {
userDB.child(mUserId).child("changes").child(mImdbID).child("triggers").child(trigger.getTriggerName()).setValue(0);
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
holder.total.setText(String.valueOf(trigger.getTriggerVotesYes()));
holder.upButton.setCount(trigger.getTriggerVotesYes());
if (trigger.getTriggerVotesTotal() != 0){
holder.total.setText(String.valueOf(trigger.getTriggerVotesTotal()));
int downButtonCount = (trigger.getTriggerVotesTotal() - trigger.getTriggerVotesYes());
holder.downButton.setCount(downButtonCount);
}
return view;
}
private static class ViewHolder {
TextView triggerName;
CounterFab upButton;
CounterFab downButton;
TextView total;
}
private void neitherButtonIsSelected(final ViewHolder holder, final Trigger trigger, final String mUserId) {
holder.upButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
triggerDB = movieDB.child(mImdbID).child("Triggers").child(trigger.getTriggerName());
triggerDB.child("triggerVotesYes").runTransaction(new Transaction.Handler() {
@Override
public Transaction.Result doTransaction(MutableData mutableData) {
int count = mutableData.getValue(Integer.class);
mutableData.setValue(count + 1);
return Transaction.success(mutableData);
}
@Override
public void onComplete(DatabaseError databaseError, boolean b, DataSnapshot dataSnapshot) {
}
});
triggerDB.child("triggerVotesTotal").runTransaction(new Transaction.Handler() {
@Override
public Transaction.Result doTransaction(MutableData mutableData) {
int count = mutableData.getValue(Integer.class);
mutableData.setValue(count + 1);
userDB.child(mUserId).child("changes").child(mImdbID).child("triggers").child(trigger.getTriggerName()).setValue(1);
return Transaction.success(mutableData);
}
@Override
public void onComplete(DatabaseError databaseError, boolean b, DataSnapshot dataSnapshot) {
}
});
userDB.child(mUserId).child("changes").child(mImdbID).child("triggers").child(trigger.getTriggerName()).setValue(1);
}
});
holder.downButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View view) {
triggerDB.child("triggerVotesTotal").runTransaction(new Transaction.Handler() {
@Override
public Transaction.Result doTransaction(MutableData mutableData) {
int count = mutableData.getValue(Integer.class);
mutableData.setValue(count + 1);
userDB.child(mUserId).child("changes").child(mImdbID).child("triggers").child(trigger.getTriggerName()).setValue(1);
return Transaction.success(mutableData);
}
@Override
public void onComplete(DatabaseError databaseError, boolean b, DataSnapshot dataSnapshot) {
}
});
userDB.child(mUserId).child("changes").child(mImdbID).child("triggers").child(trigger.getTriggerName()).setValue(1);
}
});
}
private void upButtonIsSelected(final ViewHolder holder, final Trigger trigger, final String mUserId) {
holder.upButton.setOnClickListener(null);
holder.downButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View view) {
triggerDB = movieDB.child(mImdbID).child("Triggers").child(trigger.getTriggerName());
triggerDB.child("triggerVotesYes").runTransaction(new Transaction.Handler() {
@Override
public Transaction.Result doTransaction(MutableData mutableData) {
int count = mutableData.getValue(Integer.class);
mutableData.setValue(count - 1);
userDB.child(mUserId).child("changes").child(mImdbID).child("triggers").child(trigger.getTriggerName()).setValue(-1);
return Transaction.success(mutableData);
}
@Override
public void onComplete(DatabaseError databaseError, boolean b, DataSnapshot dataSnapshot) {
holder.downButton.getBackground().setAlpha(127);
}
});
}
});
}
private void downButtonIsSelected(final ViewHolder holder, final Trigger trigger, final String mUserId) {
holder.downButton.setOnClickListener(null);
holder.upButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View view) {
triggerDB = movieDB.child(mImdbID).child("Triggers").child(trigger.getTriggerName());
triggerDB.child("triggerVotesYes").runTransaction(new Transaction.Handler() {
@Override
public Transaction.Result doTransaction(MutableData mutableData) {
int count = mutableData.getValue(Integer.class);
mutableData.setValue(count + 1);
userDB.child(mUserId).child("changes").child(mImdbID).child("triggers").child(trigger.getTriggerName()).setValue(1);
return Transaction.success(mutableData);
}
@Override
public void onComplete(DatabaseError databaseError, boolean b, DataSnapshot dataSnapshot) {
holder.downButton.getBackground().setAlpha(127);
}
});
}
});
}
}
wäre es mTriggerList oder mResultList? Auf welche Weise würde ich die Triggerklasse überschreiben? –