标题可能有点误导,我的问题更多的是为什么它以这种奇怪的方式工作.
所以我有一个具有TextView和ListView的布局的活动.我有一个长期运行的异步方法,准备在列表中显示数据.所以初始代码是这样的:
protected async override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.MyView);
await SetupData();
}
private async Task SetupData(){
Task.Run(async () => {
var data = await new SlowDataLoader().LoadDataAsync();
// For simplicity setting data on the adapter is omitted here
});
}
Run Code Online (Sandbox Code Playgroud)
它的工作原理在某种意义上说它没有错误地执行.但是,活动显示为空白屏幕,即使文本视图仅在一定延迟后呈现.因此看起来任务实际上并非异步运行.在"await"调用上设置ConfigureAwait(false)没有帮助.将SetupData()调用移动到OnPostCreate,OnResume和OnPostResume无效.唯一让TextView立即出现并在以后呈现列表的东西,当数据到达时是这样的:
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.MyView);
new Handler().PostDelayed(async ()=>{
await SetupData();
}, 100);
}
Run Code Online (Sandbox Code Playgroud)
所以问题是,为什么不呢
await SetupData().ConfigureAwait(false);
Run Code Online (Sandbox Code Playgroud)
解锁流量?为什么我们必须强制延迟异步操作的开始以让UI完成渲染,尽管如此(根据http://www.wintellect.com/devcenter/paulballard/tasks-are-still-not-threads-and -async-is-not-parallel)SetupData应该可以在这里作为一个单独的线程运行?
ps删除在适配器上设置数据的代码不会影响此行为 - 在呈现屏幕之前仍有延迟.所以我不在这里展示代码.
因此,在Nougat中,来自同一应用程序的多个通知会自动捆绑到一个组中.我在我的通知上设置了一些额外的PendingIntent,如果点击了特定的通知,它会启动一个特定的活动(深层链接).
但是,如果我点击通知包(即没有扩展组),我的应用程序就像是来自启动器一样启动 - 即它的意图是空的,没有额外的(它不是通过提供的PendingIntent启动).
如何在用户点击通知包时指定使用意图?
因此,关于如何在 Android 上进行延迟有多个类似的问题/答案。然而,他们主要专注于在 UI 线程上执行此操作。如果我需要延迟服务中的工作线程(并且我不想让线程进入睡眠状态)怎么办?Handler.postDelayed() 不起作用,因为存在“无法在线程内创建处理程序没有调用 Looper.prepare()”异常。CountDownTimer 出于同样的原因不起作用。而且我没有任何意见可以调用 runOnUiThread()。那么是在我拥有的每个线程上都有一个循环器的唯一解决方案还是有另一种方法可以做到这一点?
更新:这很愚蠢,但我在我自己的旧代码中找到了对我有用的答案:)。基本上,如果您想从非 UI 线程延迟启动 Runnable,您需要做的就是让主循环程序处理这个问题。
Handler handler = new Handler(Looper.getMainLooper());
Runnable r = new Runnable() {
@Override
public void run() {
// Do stuff to be run after a delay
// CAUTION: this won't be run on the same thread
}
};
handler.postDelayed(r, DELAY_TIME);
Run Code Online (Sandbox Code Playgroud)
缺点可能是该 Runnable 中的代码不会与原始代码在同一线程上运行。这就是为什么我不把这种方法作为被接受的答案(我承认,最初的问题听起来像是我希望在同一个非 UI 线程上发生一个定时事件。为此我还没有答案除了 Emmanuel 的那个,我必须在我的线程上附加一个 Looper)。然而,出于我的目的,这有效,因为我只需要在超时时启动服务。
在我的项目中,我有相同模式重复的屏幕 - 它基本上是视图的容器,包含带有标题,图像和特定背景的线性布局.为了避免多次复制和粘贴相同的序列,我认为我可以创建一个复合视图,扩展LinearLayout并在那里定义所有"样式",然后在我的布局中使用该组件.我按照howto和例子,让我的复合视图工作.但是,我看到的所有示例都使用结果视图,如下所示:
<com.myproject.compound.myview
...some attrs...
/>
Run Code Online (Sandbox Code Playgroud)
也就是说,没有孩子通过XML添加.我需要像这样使用它:
<com.myproject.compound.myview
...some attrs...>
<TextView
..../>
...other views...
</com.myproject.compound.myview>
Run Code Online (Sandbox Code Playgroud)
由于我正在扩展LinearLayout,我期待"myview"标签也像LinearLayout一样工作,但由于某些原因,我放在里面的项目不会被绘制.有什么我需要特别做的事情来获取内部视图吗?
我的扩展LinearLayout非常简单,我没有覆盖任何方法,只是在构造函数中调用super并像这样膨胀布局:
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.my_compound_view, this, true);
Run Code Online (Sandbox Code Playgroud)
更新:我想我会添加一个XML作为参考点:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@drawable/bg"
android:padding="12dp">
<TextView
android:id="@+id/section_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#FF0000AA" />
<ImageView
android:layout_width="match_parent"
android:layout_height="2dp"
android:src="@drawable/line" />
</LinearLayout>
Run Code Online (Sandbox Code Playgroud) 我看到这种奇怪的行为,并想问是否有人找到了解决方法.我有一个简单的RelativeLayout,里面有另一个布局.
奇怪的行为发生在代码中.如果我从嵌套布局中获取LayoutParams并将其设置回它,则会改变布局的外观.似乎某些参数在此过程中丢失了.这是代码:
RelativeLayout v = (RelativeLayout)findViewById(R.id.group1);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(v.getLayoutParams());
v.setLayoutParams(lp);
Run Code Online (Sandbox Code Playgroud)
在这个调用之后,我期待一切都保持不变,但是,我正在失去"layout_AlignParentRight"效果(至少).谁能帮我理解为什么会这样?
从实际角度来看,我所需要的只是在运行时更改group1布局的宽度.所以我通过改变上面"lp"的宽度来做到这一点,并且它可以工作,但会弄乱对齐.因此,如果有任何关于在不影响其他属性的情况下更改布局大小的替代方法的建议,请也请插入.
布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/group1"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_alignParentRight="true">
<TextView
android:layout_alignParentLeft="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test">
</TextView>
</RelativeLayout>
</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)