android - 堆栈 View 小部件中带有 RemoteViews 的 AsyncTask

标签 android view android-widget widget stackview

我试图搜索有关 StackView Widget 的信息,但我发现了很多,但没有人习惯从 url 获取数据。 所以问题是,当我处理 url 时,我的 RemoteViews 是 null ,所以它们什么都不显示。完成该过程后,我想从 asyntask 更新 RemoteViews(在同一类中)。 我该怎么做?或者同步它们?

这是我的 Widget 服务代码:

public class RSSService extends RemoteViewsService {

private ManagerRSS mr;
private Cursor c;
private int lenght;
private List<Provider> mWidgetItems = new ArrayList<Provider>();
private RemoteViews rv = null;
public ArrayList<Item> result = new ArrayList<Item>();
private boolean isFinished = false;

@Override
public void onCreate() {
    // TODO Auto-generated method stub
    mr = new ManagerRSS(this.getApplicationContext());
    mr.open();
    mr.openRead();
    c = mr.getCursor();
    lenght = c.getCount();
}

@Override
public void onDestroy() {
    // TODO Auto-generated method stub
    c.close();
    mr.close();
    super.onDestroy();
}

@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
    // TODO Auto-generated method stub
    return new RSSRemoteViewsFactory(this.getApplicationContext(), intent);
}

class RSSRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory{

    private Context mContext;
    private int mAppWidgetId;


    public RSSRemoteViewsFactory(Context applicationContext, Intent intent) {
        // TODO Auto-generated constructor stub
        mContext = applicationContext;
        mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
                AppWidgetManager.INVALID_APPWIDGET_ID);
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return lenght;
    }

    @Override
    public long getItemId(int arg0) {
        // TODO Auto-generated method stub
        return arg0;
    }

    @Override
    public RemoteViews getLoadingView() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public RemoteViews getViewAt(int position) {
        if(isFinished){
            rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item);
            rv.setTextViewText(R.id.widget_item, mWidgetItems.get(position).getTitle());
            if(mWidgetItems.get(position).getTitle().equals("El Pais")){
                rv.setImageViewResource(R.id.iNotice, R.drawable.elpais);
            }else if(mWidgetItems.get(position).getTitle().equals("Marca")){
                rv.setImageViewResource(R.id.iNotice, R.drawable.marca);
            }else if(mWidgetItems.get(position).getTitle().equals("As")){
                rv.setImageViewResource(R.id.iNotice, R.drawable.as1);
            }else if(mWidgetItems.get(position).getTitle().equals("Ideal")){
                rv.setImageViewResource(R.id.iNotice, R.drawable.ideal);
            }else{
                rv.setImageViewResource(0, R.drawable.undefined);
            }
            rv.setTextViewText(R.id.tvLastNotice, result.get(position).getTitle());
            rv.setTextViewText(R.id.tvLastNoticePublish, result.get(position).getPubDate());
            Bundle extras = new Bundle();
            extras.putString(Widget.NAME_DIARY, mWidgetItems.get(position).getTitle());
            Intent fillInIntent = new Intent();
            fillInIntent.putExtras(extras);
            rv.setOnClickFillInIntent(R.id.widget_item, fillInIntent);
            try {
                System.out.println("Loading view " + position);
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            return rv;
        }else{
            return null;
        }

    }

    @Override
    public int getViewTypeCount() {
        // TODO Auto-generated method stub
        return 1;
    }

    @Override
    public boolean hasStableIds() {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public void onCreate() {
        while(c.moveToNext()){
            String title = c.getString(c.getColumnIndex(Contrato.TableRSS.TITLE));
            String link = c.getString(c.getColumnIndex(Contrato.TableRSS.LINK));
            long _id = c.getLong(c.getColumnIndex(Contrato.TableRSS._ID));
            mWidgetItems.add(new Provider(_id, title, link));
            executeThread(link, c.getPosition());
        }
    }

    void executeThread(String type_link,int position){
        myThread exe = new myThread();
        exe.setOnlyFirst(true);
        exe.execute(new String[]{type_link});
    }

    private class myThread extends MyAsyncTask{

        @Override
        protected void onPostExecute(ArrayList<Item> result2) {
            // TODO Auto-generated method stub
            super.onPostExecute(result2);
            for(int i=0;i<result2.size();i++) result.add(result2.get(i));
            if(result.size()+1 == c.getCount()) isFinished = true;
        }
    }

    @Override
    public void onDataSetChanged() {

    }

    @Override
    public void onDestroy() {mWidgetItems.clear();}

}

这是我的 WidgetProvider :

public class Widget  extends AppWidgetProvider{

public static final String ON_TOUCH = "com.cool.nightrss.ON_TOUCH";
public static final String ID_DIARY = "com.cool.nightrss.ID_DIARY";
public static final String ID_NOTICE = "com.cool.nightrss.ID_NOTICE";
public static final String NAME_DIARY = "com.cool.nightrss.NAME_DIARY";
public static final String LINK_NOTICE = "com.cool.nightrss.LINK_NOTICE";

@Override
public void onReceive(Context context, Intent intent) {
    // TODO Auto-generated method stub
    if (intent.getAction().equals(ON_TOUCH)) {
        int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
                AppWidgetManager.INVALID_APPWIDGET_ID);
        String name = intent.getStringExtra(NAME_DIARY);
        Toast.makeText(context, "Touched view " + name +" ID "+appWidgetId, Toast.LENGTH_SHORT).show();
    }
    super.onReceive(context, intent);
}

@SuppressWarnings("deprecation")
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
        int[] appWidgetIds) {
    // TODO Auto-generated method stub
    for (int i = 0; i < appWidgetIds.length; ++i) {

        Intent intent = new Intent(context, RSSService.class);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);

        intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
        RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
        rv.setRemoteAdapter(appWidgetIds[i], R.id.stack_view, intent);

        Intent toastIntent = new Intent(context, Widget.class);
        toastIntent.setAction(Widget.ON_TOUCH);
        toastIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
        intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
        PendingIntent toastPendingIntent = PendingIntent.getBroadcast(context, 0, toastIntent,
                PendingIntent.FLAG_UPDATE_CURRENT);
        rv.setPendingIntentTemplate(R.id.stack_view, toastPendingIntent);

        appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
    }
    super.onUpdate(context, appWidgetManager, appWidgetIds);
}

最佳答案

您可以在类RSSRemoteViewsFactory 中使用方法onDataSetChanged。当您在与该工厂对应的 Collection View 上调用 AppWidgetManager notifyAppWidgetViewDataChanged 时会触发此事件。你可以在这里同步进行起重。例如,如果您需要处理图像、从网络中获取某些内容等,可以在此处同步进行。在此处完成工作时,小部件将保持其当前状态,因此您无需担心锁定小部件。

class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
private final String TAG = StackRemoteViewsFactory.class.getSimpleName();

private Context mContext;
private int mAppWidgetId;

private List<Game> mGameItems = new ArrayList<Game>();

public StackRemoteViewsFactory(Context context, Intent intent) {
    mContext = context;
    mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
            AppWidgetManager.INVALID_APPWIDGET_ID);
}

public void onCreate() {
}

public void onDestroy() {
    mGameItems.clear();
}

public int getCount() {
    return mGameItems.size();
}

public RemoteViews getViewAt(int position) {
    Game game = mGameItems.get(position);

    Bundle extras = new Bundle();
    extras.putString(StackWidgetProvider.EXTRA_ITEM, game.getGameUrl());
    Intent fillInIntent = new Intent();
    fillInIntent.putExtras(extras);
    rv.setOnClickFillInIntent(R.id.widget_item, fillInIntent);


    Bitmap bitmap = null;
    try {
        URL imageUrl = new URL(game.getImageUrl());
        bitmap = BitmapFactory.decodeStream(imageUrl.openConnection().getInputStream());
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    rv.setImageViewBitmap(R.id.widget_item, bitmap);
    return rv;
}

public RemoteViews getLoadingView() {
    return null;
}

public int getViewTypeCount() {
    return 1;
}

public long getItemId(int position) {
    return position;
}

public boolean hasStableIds() {
    return true;
}

public void onDataSetChanged() {

    final String uri = <set your url>

    DefaultHttpClient httpClient = new DefaultHttpClient();
    HttpGet httpGet = new HttpGet(uri);

    String jsonData = null;

    /**
     * Fetch JSON from web service
     * TODO: try to call a AsyncTask
     */
    try {
        HttpResponse httpResponse = httpClient.execute(httpGet);
        HttpEntity httpEntity = httpResponse.getEntity();
        InputStream inputStream = httpEntity.getContent();

        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        StringBuilder data = new StringBuilder();
        String line;
        while ((line = bufferedReader.readLine()) != null) {
            data.append(line);
        }
        jsonData = new String(data);
        Log.d(TAG, String.format("JSON: %s", jsonData));

    } catch (IOException e) {
        e.printStackTrace();
    }

    /**
     * Mapping JSON String to objects
     * TODO: Probably move the code to a dedicated class and use GSON to do the mapping?????
     */
    if(jsonData != null && !jsonData.equals("")) {
        try {
            JSONArray jsonArray = new JSONArray(jsonData);
            for(int index = 0; index < jsonArray.length(); index++) {
                JSONObject jsonObject = jsonArray.getJSONObject(index);
                String id = jsonObject.getString("id");
                String imageUrl = jsonObject.getString("imageUrl");
                String gameUrl = jsonObject.getString("gameUrl");

                mGameItems.add(
                        new Game(id, imageUrl, gameUrl)
                );
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
    Log.d(TAG, String.format("List of games: %s", mGameItems));
}

在下面的示例中,我从网络服务器获取 json,然后从每个项目获取图像。 onDataSetChanged 用于获取 json 内容,在 getViewAt 中我获取图像。

查看 Google 提供的 StackView 示例中的评论 - http://docs.huihoo.com/android/3.0/resources/samples/StackWidget/index.html

希望对你有帮助

关于android - 堆栈 View 小部件中带有 RemoteViews 的 AsyncTask,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21614460/

相关文章:

java - 访问 google 任务 api 时出现 403 禁止错误

android studio 3.0 录制视频不工作

javascript - 如何使用 android 在 webview 中播放视频?

android - 如何制作 Android 自组件并从 jar 库中使用它?

java - 使用按钮创建文件

android - Android 应用中的 Admob&Internet

ruby-on-rails - 如何在 JRuby on Rails 的开发模式下启用 View 文件的自动重新加载?

Android动画下拉/向上 View 正确

android - 专用安卓3D引擎

android - 简单的游标适配器问题