2017-10-26 10 views
0

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); 
        } 
       }); 
      } 
     }); 
    } 
} 

Antwort

0

Folgende Dinge könnten Ihnen helfen.

  • Verwenden android:stackFromBottom="true" im xml Ihrer ListView
  • Statt mTriggerList.clear(); Verwendung bei der Aktualisierung, tun es nicht klar, und fügen Sie den Artikel nur aufzulisten, wenn das Element nicht existiert bereits in der Liste.

ZB.

for(Trigger trigger: triggerSnapShot...){ 
    if (!mTriggerList.contains(trigger)){ 
     mTriggerList.add(trigger); 
    } 
} 

Sie müssen möglicherweise die equals Methode in der Klasse Trigger um außer Kraft zu setzen, das Verfahren contains Arbeit richtig zu machen.

+0

wäre es mTriggerList oder mResultList? Auf welche Weise würde ich die Triggerklasse überschreiben? –