2017-10-26 15 views
0

firebaseをバックエンドとして使用するアンドロイドアプリで投票システムを作成しています。私は自分の履歴からユーザの投票ステータスを取得し、それに応じてビューを更新し、ボタンの投票に応答する処理中です。私が抱えている問題は、ユーザが上下の投票ボタンをクリックするとリストビューを再描画し、時には2つのオプションを省略し、常にビューのスクロールを先頭に戻してしまうことです。そのリストビューを完全に再描画せずにリストビュー内のデータを更新できますか?もしそうなら、どうですか?リストビューを再描画せずにfirebase情報を更新

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

答えて

0

物事はあなたを助けるかもしれません後。

  • あなたListView
  • 代わりに更新する際mTriggerList.clear();を使用するのXMLで使用android:stackFromBottom="true"、それをクリアしないとアイテムがすでにリストに存在しない場合にのみ、リストに項目を追加します。

例:

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

あなたは正しく方法contains仕事をするためにTriggerクラスのequalsメソッドをオーバーライドする必要があるかもしれません。

+0

mTriggerListまたはmResultListですか?どのような方法でトリガークラスをオーバーライドするのですか? –

関連する問題