Android Open Source - Rss-App-for-tumblr R S S Overview List Adapter






From Project

Back to project page Rss-App-for-tumblr.

License

The source code is released under:

GNU General Public License

If you think the Android project Rss-App-for-tumblr listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/**
 * Ace Shooting/*  w  ww . j av a 2 s.  c  o m*/
 *
 * Copyright (c) 2014 Ace Shooting
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

package com.aceshooting.rssapp;

import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.os.Handler;
import android.util.TypedValue;
import android.view.View;
import android.widget.ResourceCursorAdapter;
import android.widget.TextView;

import com.aceshooting.rssapp.provider.FeedData;

import java.text.DateFormat;
import java.util.Date;
import java.util.Vector;

public class RSSOverviewListAdapter extends ResourceCursorAdapter {
  private static final String COUNT_UNREAD = "COUNT(*) - COUNT(readdate)";
  
  private static final String COUNT = "COUNT(*)";
  
  private String COLON;
  
  private int nameColumnPosition;
  
  private int lastUpdateColumn;
  
  private int idPosition;
  
  private int linkPosition;
  
  private int errorPosition;
  
  private int iconPosition;
  
  private Handler handler;
  
  private SimpleTask updateTask;
  
  private boolean feedSort;
  
  private Vector<View> sortViews;
  
  private DateFormat dateFormat;
  
  private DateFormat timeFormat;
  
  public RSSOverviewListAdapter(Activity activity) {
    super(activity, R.layout.feedlistitem, activity.managedQuery(FeedData.FeedColumns.CONTENT_URI, null, null, null, null));
    nameColumnPosition = getCursor().getColumnIndex(FeedData.FeedColumns.NAME);
    lastUpdateColumn = getCursor().getColumnIndex(FeedData.FeedColumns.LASTUPDATE);
    idPosition = getCursor().getColumnIndex(FeedData.FeedColumns._ID);
    linkPosition = getCursor().getColumnIndex(FeedData.FeedColumns.URL);
    errorPosition = getCursor().getColumnIndex(FeedData.FeedColumns.ERROR);
    iconPosition = getCursor().getColumnIndex(FeedData.FeedColumns.ICON);
    COLON = activity.getString(R.string.colon);
    handler = new Handler();
    updateTask = new SimpleTask() {
      @Override
      public void runControlled() {
        RSSOverviewListAdapter.super.onContentChanged();
        cancel(); // cancel the task such that it does not run more than once without explicit intention
      }
      
      @Override
      public void postRun() {
        if (getPostCount() > 1) { // enforce second run even if task is canceled
          handler.postDelayed(updateTask, 1500);
        }
      }
    };
    sortViews = new Vector<View>();
    dateFormat = android.text.format.DateFormat.getDateFormat(activity);
    timeFormat = android.text.format.DateFormat.getTimeFormat(activity);
  }

  @Override
  public void bindView(View view, Context context, Cursor cursor) {
    TextView textView = ((TextView) view.findViewById(android.R.id.text1));
    
    textView.setSingleLine();
    
    Cursor countCursor = context.getContentResolver().query(FeedData.EntryColumns.CONTENT_URI(cursor.getString(idPosition)), new String[] {COUNT_UNREAD, COUNT}, null, null, null);
    
    countCursor.moveToFirst();
    
    int unreadCount = countCursor.getInt(0);
    
    int count = countCursor.getInt(1);
    
    countCursor.close();
    
    long timestamp = cursor.getLong(lastUpdateColumn);
    
    TextView updateTextView = ((TextView) view.findViewById(android.R.id.text2));;
    
    if (cursor.isNull(errorPosition)) {
      Date date = new Date(timestamp);
      
      updateTextView.setText(new StringBuilder(context.getString(R.string.update)).append(COLON).append(timestamp == 0 ? context.getString(R.string.never) : new StringBuilder(dateFormat.format(date)).append(' ').append(timeFormat.format(date)).append(Strings.COMMASPACE).append(unreadCount).append('/').append(count).append(' ').append(context.getString(R.string.unread))));
    } else {
      updateTextView.setText(new StringBuilder(context.getString(R.string.error)).append(COLON).append(cursor.getString(errorPosition)));
    }
    textView.setEnabled(unreadCount > 0);
    
    byte[] iconBytes = cursor.getBlob(iconPosition);
    
    if (iconBytes != null && iconBytes.length > 0) {
      Bitmap bitmap = BitmapFactory.decodeByteArray(iconBytes, 0, iconBytes.length);
      
      if (bitmap != null && bitmap.getHeight() > 0 && bitmap.getWidth() > 0) {
        int bitmapSizeInDip = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 18f, context.getResources().getDisplayMetrics());
        
        if (bitmap.getHeight() != bitmapSizeInDip) {
          bitmap = Bitmap.createScaledBitmap(bitmap, bitmapSizeInDip, bitmapSizeInDip, false);
        }
        textView.setCompoundDrawablesWithIntrinsicBounds(new BitmapDrawable(bitmap), null, null, null);
        textView.setText(" " + (cursor.isNull(nameColumnPosition) ? cursor.getString(linkPosition) : cursor.getString(nameColumnPosition)));
      } else {
        textView.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null);
        textView.setText(cursor.isNull(nameColumnPosition) ? cursor.getString(linkPosition) : cursor.getString(nameColumnPosition));
      }
    } else {
      view.setTag(null);
      textView.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null);
      textView.setText(cursor.isNull(nameColumnPosition) ? cursor.getString(linkPosition) : cursor.getString(nameColumnPosition));
    }
    
    View sortView = view.findViewById(R.id.sortitem);
    
    if (!sortViews.contains(sortView)) { // as we are reusing views, this is fine
      sortViews.add(sortView);
    }
    sortView.setVisibility(feedSort ? View.VISIBLE : View.GONE);
  }

  @Override
  protected synchronized void onContentChanged() {
    /*
     * we delay the second(!) content change by 1.5 second such that it gets called at most once per 1.5 seconds
     * to take stress away from the UI and avoid not needed updates
     */
    if (!updateTask.isPosted()) {
      super.onContentChanged();
      updateTask.post(2); // we post 2 tasks
      handler.postDelayed(updateTask, 1500); // waits one second until the task gets unposted
      updateTask.cancel(); // put the canceled task in the queue to enable it again optionally
    } else {
      if (updateTask.getPostCount() < 2) {
        updateTask.post(); // enables the task and adds a new one
      } else {
        updateTask.enable();
      }
    }
  }

  public void setFeedSortEnabled(boolean enabled) {
    feedSort = enabled;
    
    /* we do not want to call notifyDataSetChanged as this requeries the cursor*/
    int visibility = feedSort ? View.VISIBLE : View.GONE;
    
    for (View sortView : sortViews) {
      sortView.setVisibility(visibility);
    }
  }
}




Java Source Code List

com.aceshooting.rssapp.Animations.java
com.aceshooting.rssapp.ApplicationPreferencesActivity.java
com.aceshooting.rssapp.BASE64.java
com.aceshooting.rssapp.BootCompletedBroadcastReceiver.java
com.aceshooting.rssapp.CompatibilityHelper.java
com.aceshooting.rssapp.EmptyActivity.java
com.aceshooting.rssapp.EntriesListActivity.java
com.aceshooting.rssapp.EntriesListAdapter.java
com.aceshooting.rssapp.EntryActivity.java
com.aceshooting.rssapp.FeedConfigActivity.java
com.aceshooting.rssapp.MainTabActivity.java
com.aceshooting.rssapp.MyApplication.java
com.aceshooting.rssapp.RSSOverviewListAdapter.java
com.aceshooting.rssapp.RSSOverview.java
com.aceshooting.rssapp.RefreshBroadcastReceiver.java
com.aceshooting.rssapp.Requeryable.java
com.aceshooting.rssapp.SimpleTask.java
com.aceshooting.rssapp.Strings.java
com.aceshooting.rssapp.handler.PictureFilenameFilter.java
com.aceshooting.rssapp.handler.RSSHandler.java
com.aceshooting.rssapp.provider.FeedDataContentProvider.java
com.aceshooting.rssapp.provider.FeedData.java
com.aceshooting.rssapp.provider.OPML.java
com.aceshooting.rssapp.service.FetcherService.java
com.aceshooting.rssapp.service.RefreshService.java
com.aceshooting.rssapp.widget.ColorPickerDialogPreference.java
com.aceshooting.rssapp.widget.SparseRSSAppWidgetProvider.java
com.aceshooting.rssapp.widget.WidgetConfigActivity.java